Skip to content

Commit 01544f1

Browse files
feat: initial commit
0 parents  commit 01544f1

File tree

11 files changed

+770
-0
lines changed

11 files changed

+770
-0
lines changed

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
build/
2+
dist/
3+
*.egg-info/
4+
.eggs/
5+
6+
__pycache__/
7+
*.py[cod]
8+
*$py.class
9+
10+
venv/
11+
env/
12+
.venv/
13+
14+
.vscode/
15+
.idea/

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 GREEN-API
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# MAX BOT API Chatbot (Python)
2+
3+
`maxbot-chatbot-python` — это асинхронный фреймворк для создания масштабируемых ботов для **MAX BOT API** на языке **Python**.
4+
5+
Построенная на основе [`maxbot_api_client_python`](https://github.com/green-api/maxbot-api-client-python), эта библиотека предоставляет чистый маршрутизатор, автоматическое получение обновлений (*Long Polling*) и надежный менеджер состояний (*FSM*) для построения многошаговых диалоговых сценариев.
6+
7+
Для использования библиотеки требуется получить токен бота в консоли разработчика **MAX API**.
8+
Ознакомиться с инструкцией можно [по ссылке](https://green-api.com/max-bot-api/docs/before-start/).
9+
10+
## API
11+
12+
Документацию по **REST API MAX** можно найти по ссылке [dev.max.ru/docs-api](https://dev.max.ru/docs-api). Библиотека является оберткой для REST API, поэтому документация по указанной выше ссылке также применима к используемым здесь моделям.
13+
14+
Документацию по **MAX BOT API** можно найти по ссылке [green-api.com/max-bot-api/docs](https://green-api.com/max-bot-api/docs/).
15+
16+
## Поддержка
17+
18+
[![Support](https://img.shields.io/badge/support@green--api.com-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:support@green-api.com)
19+
[![Support](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/greenapi_support_ru_bot)
20+
[![Support](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://wa.me/77780739095)
21+
22+
## Руководства и новости
23+
24+
[![Guides](https://img.shields.io/badge/YouTube-%23FF0000.svg?style=for-the-badge&logo=YouTube&logoColor=white)](https://www.youtube.com/@green-api)
25+
[![News](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/green_api)
26+
[![News](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://whatsapp.com/channel/0029VaHUM5TBA1f7cG29nO1C)
27+
28+
## Установка
29+
30+
**Убедитесь, что у вас установлен Python версии 3.12 или выше.**
31+
32+
```bash
33+
python --version
34+
```
35+
36+
**Установите библиотеку:**
37+
38+
```bash
39+
pip install maxbot-chatbot-python
40+
```
41+
42+
---
43+
44+
## Использование и примеры
45+
46+
**Параметры конфигурации:**
47+
48+
- `base_url` - Базовый URL-адрес серверов платформы MaxBot. Все методы API будут маршрутизироваться по этому корневому адресу. Актуальный адрес указан в [официальной документации](https://dev.max.ru/docs-api).
49+
- `token` - Уникальный секретный ключ авторизации (API-ключ) вашего бота. Получить его можно в личном кабинете после [регистрации или создании бота](https://green-api.com/max-bot-api/docs/before-start/) на платформе [business.max.ru](https://business.max.ru/).
50+
- `ratelimiter` - Встроенный ограничитель частоты запросов. Он контролирует количество исходящих запросов в секунду (RPS), защищая бота от блокировки со стороны сервера за превышение лимитов. Рекомендуемое значение — не менее 25.
51+
- `timeout` - Максимальное время ожидания ответа от сервера (в секундах). Если сервер не ответит в течение этого времени, запрос будет завершен с ошибкой. Оптимальное значение — 30 секунд.
52+
53+
### Инициализация бота
54+
55+
Использование асинхронного контекстного менеджера (`async with API(...)`) гарантирует безопасное закрытие сетевых соединений при остановке бота.
56+
57+
```python
58+
import asyncio
59+
60+
from maxbot_api_client_python import API, Config
61+
from maxbot_chatbot_python import Bot, MapStateManager
62+
63+
async def main():
64+
cfg = Config(
65+
base_url="https://platform-api.max.ru/",
66+
token="YOUR_BOT_TOKEN",
67+
ratelimiter=25,
68+
timeout=35
69+
)
70+
71+
async with API(cfg) as api_client:
72+
bot = Bot(api_client)
73+
bot.state_manager = MapStateManager(init_data={})
74+
75+
polling_task = asyncio.create_task(bot.start_polling())
76+
77+
try:
78+
await polling_task
79+
except asyncio.CancelledError:
80+
pass
81+
82+
if __name__ == "__main__":
83+
try:
84+
asyncio.run(main())
85+
except KeyboardInterrupt:
86+
print("Bot stopped by user")
87+
```
88+
89+
### Маршрутизация команд, сообщений и коллбэков
90+
91+
Встроенный **маршрутизатор** (`Router`) позволяет легко обрабатывать конкретные команды (начинающиеся со слэша `/`) и нажатия на **inline-кнопки** (коллбэки).
92+
93+
```python
94+
@bot.router.command("/start")
95+
async def start_command(notification):
96+
await notification.reply("Hello! Welcome to the MAX Bot.")
97+
98+
@bot.router.register("message_created")
99+
async def ping_handler(notification):
100+
try:
101+
if notification.text() == "ping":
102+
await notification.reply("pong")
103+
except ValueError:
104+
pass
105+
106+
@bot.router.callback("accept_rules")
107+
async def rules_callback(notification):
108+
await notification.reply("*Thank you for accepting the rules!*", format_type="markdown")
109+
await notification.answer_callback("Success!")
110+
```
111+
112+
### Управление состояниями и Сцены (FSM)
113+
114+
Для сложных многошаговых диалогов (например, регистрация или анкетирование) используйте **Менеджер состояний** (`StateManager`) и **Сцены** (`Scene`).
115+
116+
```python
117+
from maxbot_chatbot_python import Scene
118+
119+
class RegistrationScene(Scene):
120+
async def start(self, notification):
121+
try:
122+
text = notification.text()
123+
except ValueError:
124+
return
125+
126+
if text == "/start":
127+
await notification.reply("Let's register! What is your *login*?", "markdown")
128+
return
129+
130+
if len(text) >= 4:
131+
if notification.state_manager:
132+
notification.state_manager.update_state_data(notification.state_id, {"login": text})
133+
134+
await notification.reply(f"**Login** `{text}` accepted. Now enter your **password**:", "markdown")
135+
notification.activate_next_scene(PasswordScene())
136+
else:
137+
await notification.reply("Login must be **at least 4 characters long**.", "markdown")
138+
139+
class PasswordScene(Scene):
140+
async def start(self, notification):
141+
try:
142+
password = notification.text()
143+
except ValueError:
144+
return
145+
146+
state_data = notification.state_manager.get_state_data(notification.state_id)
147+
login = state_data.get("login", "Unknown")
148+
149+
await notification.reply(f"Success! Profile created.\nLogin: `{login}`\nPass: `{password}`", "markdown")
150+
151+
notification.activate_next_scene(RegistrationScene())
152+
153+
@bot.router.register("message_created")
154+
async def fsm_handler(notification):
155+
if not notification.state_manager.get(notification.state_id):
156+
notification.state_manager.create(notification.state_id)
157+
158+
current_scene = notification.get_current_scene()
159+
if current_scene:
160+
await current_scene.start(notification)
161+
```
162+
163+
### Ответ с медиафайлами
164+
165+
Обертка `Notification` содержит готовые асинхронные методы для отправки файлов, геолокаций, стикеров и статусов набора текста.
166+
167+
```python
168+
@bot.router.command("/photo")
169+
async def send_photo(notification):
170+
await notification.show_action("sending_photo")
171+
172+
await notification.reply_with_media(
173+
text="Check out this image!",
174+
format_type="markdown",
175+
file_source="https://storage.yandexcloud.net/sw-prod-03-test/ChatBot/corgi.jpg"
176+
)
177+
```
178+
179+
### Эхо-бот
180+
181+
```python
182+
import asyncio
183+
184+
from maxbot_api_client_python import API, Config
185+
from maxbot_chatbot_python import Bot, MapStateManager
186+
187+
async def main():
188+
cfg = Config(
189+
base_url="https://platform-api.max.ru/",
190+
token="YOUR_BOT_TOKEN",
191+
ratelimiter=25
192+
)
193+
194+
async with API(cfg) as api_client:
195+
bot = Bot(api_client)
196+
bot.state_manager = MapStateManager(init_data={})
197+
198+
@bot.router.register("message_created")
199+
async def echo_handler(notification):
200+
try:
201+
text = notification.text()
202+
await notification.reply(f"**Echo:** {text}", "markdown")
203+
except Exception as e:
204+
print(f"Error handling message: {e}")
205+
206+
polling_task = asyncio.create_task(bot.start_polling())
207+
208+
try:
209+
await polling_task
210+
except asyncio.CancelledError:
211+
pass
212+
213+
if __name__ == "__main__":
214+
try:
215+
asyncio.run(main())
216+
except KeyboardInterrupt:
217+
print("Bot stopped by user (KeyboardInterrupt)")
218+
```
219+
```

examples/echoBot.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import asyncio
2+
3+
from maxbot_api_client_python import API, Config
4+
from maxbot_chatbot_python import Bot, MapStateManager
5+
6+
async def main():
7+
8+
cfg = Config(
9+
base_url="https://platform-api.max.ru/", # Base url for MAX API requests
10+
token="YOUR_BOT_TOKEN", # Max bot token
11+
ratelimiter=25
12+
)
13+
14+
async with API(cfg) as api_client:
15+
bot = Bot(api_client)
16+
bot.state_manager = MapStateManager(init_data={})
17+
18+
@bot.router.register("message_created")
19+
async def echo_handler(notification):
20+
try:
21+
text = notification.text()
22+
await notification.reply(f"**Echo:** {text}", "markdown")
23+
except Exception as e:
24+
print(f"Error handling message:", str(e))
25+
26+
polling_task = asyncio.create_task(bot.start_polling())
27+
28+
try:
29+
await polling_task
30+
except asyncio.CancelledError:
31+
pass
32+
33+
if __name__ == "__main__":
34+
try:
35+
asyncio.run(main())
36+
except KeyboardInterrupt:
37+
print("Bot stopped by user (KeyboardInterrupt)")

maxbot_chatbot_python/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from maxbot_chatbot_python.bot import Bot
2+
from maxbot_chatbot_python.state import MapStateManager, Scene, State
3+
from maxbot_chatbot_python.notification import Notification
4+
from maxbot_chatbot_python.router import Router
5+
6+
__all__ = [
7+
"Bot",
8+
"MapStateManager",
9+
"Scene",
10+
"State",
11+
"Notification",
12+
"Router"
13+
]

maxbot_chatbot_python/bot.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import asyncio
2+
from maxbot_api_client_python.types.models import GetUpdatesReq
3+
from maxbot_chatbot_python.router import Router
4+
from maxbot_chatbot_python.notification import Notification
5+
6+
class Bot:
7+
def __init__(self, api_client):
8+
self.api = api_client
9+
self.router = Router()
10+
self.state_manager = None
11+
self.marker = 0
12+
13+
async def start_polling(self):
14+
print("Bot is running. Start polling...")
15+
16+
while True:
17+
try:
18+
resp = await self.api.subscriptions.get_updates_async(
19+
GetUpdatesReq(
20+
marker=self.marker,
21+
timeout=25
22+
)
23+
)
24+
25+
if getattr(resp, 'marker', 0) != 0:
26+
self.marker = resp.marker
27+
28+
updates = getattr(resp, 'updates', [])
29+
for update in updates:
30+
asyncio.create_task(self.process_update(update))
31+
32+
except asyncio.CancelledError:
33+
print("Stop polling...")
34+
break
35+
except Exception as e:
36+
print(f"Error receiving updates: {e}")
37+
await asyncio.sleep(2)
38+
39+
async def process_update(self, update):
40+
notif = Notification(
41+
update=update,
42+
bot=self.api,
43+
state_manager=self.state_manager
44+
)
45+
await self.router.publish(notif)

0 commit comments

Comments
 (0)