smart-bot-factory 0.1.6__tar.gz → 0.1.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of smart-bot-factory might be problematic. Click here for more details.
- smart_bot_factory-0.1.8/PKG-INFO +126 -0
- smart_bot_factory-0.1.8/README.md +93 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/best-valera.py +9 -60
- {smart_bot_factory-0.1.6/smart_bot_factory/configs/growthmed-october-24 → smart_bot_factory-0.1.8/bots/best-valera}/prompts/final_instructions.txt +2 -2
- smart_bot_factory-0.1.8/bots/best-valera/tests/quick_scenarios.yaml +66 -0
- {smart_bot_factory-0.1.6/bots/best-valera → smart_bot_factory-0.1.8/bots/valera}/prompts/final_instructions.txt +0 -6
- smart_bot_factory-0.1.8/bots/valera/tests/quick_scenarios.yaml +66 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/pyproject.toml +2 -2
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/cli.py +10 -61
- smart_bot_factory-0.1.8/smart_bot_factory/configs/growthmed-october-24/prompts/2product_info.txt +582 -0
- smart_bot_factory-0.1.8/smart_bot_factory/configs/growthmed-october-24/prompts/3objection_handling.txt +66 -0
- smart_bot_factory-0.1.8/smart_bot_factory/configs/growthmed-october-24/prompts/final_instructions.txt +212 -0
- smart_bot_factory-0.1.8/smart_bot_factory/configs/growthmed-october-24/prompts/help_message.txt +28 -0
- smart_bot_factory-0.1.8/smart_bot_factory/configs/growthmed-october-24/prompts/welcome_message.txt +8 -0
- smart_bot_factory-0.1.8/smart_bot_factory/configs/growthmed-october-24/tests/realistic_scenarios.yaml +108 -0
- smart_bot_factory-0.1.8/smart_bot_factory/configs/growthmed-october-24/tests/scenario_examples.yaml +46 -0
- smart_bot_factory-0.1.8/smart_bot_factory/configs/growthmed-october-24/welcome_file/welcome_file_msg.txt +16 -0
- smart_bot_factory-0.1.8/smart_bot_factory/configs/growthmed-october-24/welcome_file//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/core/bot_utils.py +15 -25
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/core/decorators.py +582 -83
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/core/message_sender.py +207 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/core/router.py +50 -9
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/core/router_manager.py +18 -4
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/creation/bot_builder.py +7 -2
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/handlers/handlers.py +110 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/integrations/supabase_client.py +74 -4
- smart_bot_factory-0.1.8/smart_bot_factory/message/__init__.py +16 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/supabase/__init__.py +1 -1
- smart_bot_factory-0.1.8/smart_bot_factory/supabase/client.py +524 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/uv.lock +1 -1
- smart_bot_factory-0.1.8/valera.py +71 -0
- smart_bot_factory-0.1.6/PKG-INFO +0 -466
- smart_bot_factory-0.1.6/README.md +0 -433
- smart_bot_factory-0.1.6/ROUTER_ARCHITECTURE.md +0 -152
- smart_bot_factory-0.1.6/bot_testing.py +0 -977
- smart_bot_factory-0.1.6/example_usage.py +0 -69
- smart_bot_factory-0.1.6/smart_bot_factory/configs/growthmed-october-24/tests/quick_scenarios.yaml +0 -133
- smart_bot_factory-0.1.6/smart_bot_factory/message/__init__.py +0 -12
- smart_bot_factory-0.1.6/smart_bot_factory/supabase/example_usage.py +0 -1
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/.github/ISSUE_TEMPLATE//342/234/250-/320/267/320/260/320/277/321/200/320/276/321/201-/321/204/321/203/320/275/320/272/321/206/320/270/320/270.md" +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/.github/ISSUE_TEMPLATE//360/237/220/233-/320/261/320/260/320/263-/321/200/320/265/320/277/320/276/321/200/321/202.md" +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/.github/workflows/ci.yml +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/.github/workflows/publish-private.yml +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/.github/workflows/publish.yml +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/.gitignore +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/.python-version +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/CLIENTS_USAGE.md +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/Dockerfile +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/LICENSE +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/bots/best-valera/prompts/1sales_context.txt +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/bots/best-valera/prompts/2product_info.txt +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/bots/best-valera/prompts/3objection_handling.txt +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/bots/best-valera/prompts/help_message.txt +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/bots/best-valera/prompts/welcome_message.txt +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/bots/best-valera/tests/realistic_scenarios.yaml +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/bots/best-valera/tests/scenario_examples.yaml +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/bots/best-valera/welcome_files/welcome_file_msg.txt +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/bots/best-valera/welcome_files//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf" +0 -0
- {smart_bot_factory-0.1.6/smart_bot_factory/configs/growthmed-october-24 → smart_bot_factory-0.1.8/bots/valera}/prompts/2product_info.txt +0 -0
- {smart_bot_factory-0.1.6/smart_bot_factory/configs/growthmed-october-24 → smart_bot_factory-0.1.8/bots/valera}/prompts/3objection_handling.txt +0 -0
- {smart_bot_factory-0.1.6/smart_bot_factory/configs/growthmed-october-24 → smart_bot_factory-0.1.8/bots/valera}/prompts/help_message.txt +0 -0
- {smart_bot_factory-0.1.6/smart_bot_factory/configs/growthmed-october-24 → smart_bot_factory-0.1.8/bots/valera}/prompts/welcome_message.txt +0 -0
- {smart_bot_factory-0.1.6/smart_bot_factory/configs/growthmed-october-24 → smart_bot_factory-0.1.8/bots/valera}/tests/realistic_scenarios.yaml +0 -0
- {smart_bot_factory-0.1.6/smart_bot_factory/configs/growthmed-october-24 → smart_bot_factory-0.1.8/bots/valera}/tests/scenario_examples.yaml +0 -0
- {smart_bot_factory-0.1.6/smart_bot_factory/configs/growthmed-october-24/welcome_file → smart_bot_factory-0.1.8/bots/valera/welcome_files}/welcome_file_msg.txt +0 -0
- {smart_bot_factory-0.1.6/configs/valera/welcome_file → smart_bot_factory-0.1.8/bots/valera/welcome_files}//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf" +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/configs/valera/cats//320/224/320/276/320/263/320/276/320/262/320/276/321/200.pdf" +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/configs/valera/cats//320/272/320/276/320/275/320/270.jpg" +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/configs/valera/cats//320/272/320/276/321/202.jpg" +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/configs/valera/cats//320/273/320/265/321/201.jpg" +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/configs/valera/tests/fixes_elina.yaml +0 -0
- {smart_bot_factory-0.1.6/smart_bot_factory/configs/growthmed-october-24 → smart_bot_factory-0.1.8/configs/valera}/welcome_file//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf" +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/create_tag.sh +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/docker-compose.yml +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/env.example +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/requirements.txt +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/save_backup.sh +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/save_fixes.sh +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/__init__.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/admin/__init__.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/admin/admin_logic.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/admin/admin_manager.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/admin/admin_migration.sql +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/admin/admin_tester.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/admin/timeout_checker.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/analytics/analytics_manager.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/config.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/configs/growthmed-october-24/prompts/1sales_context.txt +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064229.txt +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064335.txt +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064638.txt +0 -0
- {smart_bot_factory-0.1.6/bots/best-valera → smart_bot_factory-0.1.8/smart_bot_factory/configs/growthmed-october-24}/tests/quick_scenarios.yaml +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/core/conversation_manager.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/core/states.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/creation/__init__.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/creation/bot_testing.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/database/database_structure.sql +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/database/schema.sql +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/event/__init__.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/integrations/openai_client.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/router/__init__.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/setup_checker.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/utils/__init__.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/utils/debug_routing.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/utils/prompt_loader.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/smart_bot_factory/utm_link_generator.py +0 -0
- {smart_bot_factory-0.1.6 → smart_bot_factory-0.1.8}/system_prompt_example.txt +0 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: smart-bot-factory
|
|
3
|
+
Version: 0.1.8
|
|
4
|
+
Summary: Библиотека для создания умных чат-ботов
|
|
5
|
+
Author-email: Kopatych <kopatych@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: chatbot,cli,openai,supabase,telegram
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Framework :: AsyncIO
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Communications :: Chat
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Requires-Dist: aiofiles>=23.0.0
|
|
24
|
+
Requires-Dist: aiogram>=3.4.1
|
|
25
|
+
Requires-Dist: click>=8.0.0
|
|
26
|
+
Requires-Dist: openai>=1.12.0
|
|
27
|
+
Requires-Dist: project-root-finder>=1.9
|
|
28
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
29
|
+
Requires-Dist: pytz>=2023.3
|
|
30
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
31
|
+
Requires-Dist: supabase>=2.3.4
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# Smart Bot Factory
|
|
35
|
+
|
|
36
|
+
Библиотека для создания умных чат-ботов с использованием OpenAI, Telegram и Supabase.
|
|
37
|
+
|
|
38
|
+
## Установка
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install smart-bot-factory
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Быстрый старт
|
|
45
|
+
|
|
46
|
+
1. Создайте нового бота:
|
|
47
|
+
```bash
|
|
48
|
+
sbf create my-bot
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
2. Настройте конфигурацию в `bots/my-bot/.env`
|
|
52
|
+
|
|
53
|
+
3. Запустите бота:
|
|
54
|
+
```bash
|
|
55
|
+
sbf run my-bot
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Возможности
|
|
59
|
+
|
|
60
|
+
- 🤖 Интеграция с OpenAI GPT для умных ответов
|
|
61
|
+
- 📱 Поддержка Telegram Bot API через aiogram
|
|
62
|
+
- 💾 Хранение данных в Supabase
|
|
63
|
+
- 🔄 Система событий и обработчиков
|
|
64
|
+
- ⏰ Планировщик задач
|
|
65
|
+
- 🧪 Встроенная система тестирования
|
|
66
|
+
- 📝 Управление промптами
|
|
67
|
+
- 🛠️ Удобный CLI интерфейс
|
|
68
|
+
|
|
69
|
+
## CLI команды
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Создать нового бота
|
|
73
|
+
sbf create my-bot
|
|
74
|
+
|
|
75
|
+
# Запустить бота
|
|
76
|
+
sbf run my-bot
|
|
77
|
+
|
|
78
|
+
# Показать список ботов
|
|
79
|
+
sbf list
|
|
80
|
+
|
|
81
|
+
# Управление промптами
|
|
82
|
+
sbf prompts my-bot --list
|
|
83
|
+
sbf prompts my-bot --edit welcome_message
|
|
84
|
+
sbf prompts my-bot --add new_prompt
|
|
85
|
+
|
|
86
|
+
# Запустить тесты
|
|
87
|
+
sbf test my-bot
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Пример использования
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from smart_bot_factory import BotBuilder, event_handler, schedule_task
|
|
94
|
+
|
|
95
|
+
# Обработчик события
|
|
96
|
+
@event_handler("book_appointment", "Запись на прием")
|
|
97
|
+
async def handle_booking(user_id: int, event_data: dict):
|
|
98
|
+
# Логика обработки записи на прием
|
|
99
|
+
return {"status": "success"}
|
|
100
|
+
|
|
101
|
+
# Запланированная задача
|
|
102
|
+
@schedule_task("send_reminder", "Отправка напоминания")
|
|
103
|
+
async def send_reminder(user_id: int, message: str):
|
|
104
|
+
# Логика отправки напоминания
|
|
105
|
+
return {"status": "sent"}
|
|
106
|
+
|
|
107
|
+
# Запуск бота
|
|
108
|
+
async def main():
|
|
109
|
+
bot = BotBuilder("my-bot")
|
|
110
|
+
await bot.build()
|
|
111
|
+
await bot.start()
|
|
112
|
+
|
|
113
|
+
if __name__ == "__main__":
|
|
114
|
+
asyncio.run(main())
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Требования
|
|
118
|
+
|
|
119
|
+
- Python 3.9+
|
|
120
|
+
- OpenAI API ключ
|
|
121
|
+
- Telegram Bot Token
|
|
122
|
+
- Supabase проект
|
|
123
|
+
|
|
124
|
+
## Лицензия
|
|
125
|
+
|
|
126
|
+
MIT
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Smart Bot Factory
|
|
2
|
+
|
|
3
|
+
Библиотека для создания умных чат-ботов с использованием OpenAI, Telegram и Supabase.
|
|
4
|
+
|
|
5
|
+
## Установка
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install smart-bot-factory
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Быстрый старт
|
|
12
|
+
|
|
13
|
+
1. Создайте нового бота:
|
|
14
|
+
```bash
|
|
15
|
+
sbf create my-bot
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
2. Настройте конфигурацию в `bots/my-bot/.env`
|
|
19
|
+
|
|
20
|
+
3. Запустите бота:
|
|
21
|
+
```bash
|
|
22
|
+
sbf run my-bot
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Возможности
|
|
26
|
+
|
|
27
|
+
- 🤖 Интеграция с OpenAI GPT для умных ответов
|
|
28
|
+
- 📱 Поддержка Telegram Bot API через aiogram
|
|
29
|
+
- 💾 Хранение данных в Supabase
|
|
30
|
+
- 🔄 Система событий и обработчиков
|
|
31
|
+
- ⏰ Планировщик задач
|
|
32
|
+
- 🧪 Встроенная система тестирования
|
|
33
|
+
- 📝 Управление промптами
|
|
34
|
+
- 🛠️ Удобный CLI интерфейс
|
|
35
|
+
|
|
36
|
+
## CLI команды
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Создать нового бота
|
|
40
|
+
sbf create my-bot
|
|
41
|
+
|
|
42
|
+
# Запустить бота
|
|
43
|
+
sbf run my-bot
|
|
44
|
+
|
|
45
|
+
# Показать список ботов
|
|
46
|
+
sbf list
|
|
47
|
+
|
|
48
|
+
# Управление промптами
|
|
49
|
+
sbf prompts my-bot --list
|
|
50
|
+
sbf prompts my-bot --edit welcome_message
|
|
51
|
+
sbf prompts my-bot --add new_prompt
|
|
52
|
+
|
|
53
|
+
# Запустить тесты
|
|
54
|
+
sbf test my-bot
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Пример использования
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from smart_bot_factory import BotBuilder, event_handler, schedule_task
|
|
61
|
+
|
|
62
|
+
# Обработчик события
|
|
63
|
+
@event_handler("book_appointment", "Запись на прием")
|
|
64
|
+
async def handle_booking(user_id: int, event_data: dict):
|
|
65
|
+
# Логика обработки записи на прием
|
|
66
|
+
return {"status": "success"}
|
|
67
|
+
|
|
68
|
+
# Запланированная задача
|
|
69
|
+
@schedule_task("send_reminder", "Отправка напоминания")
|
|
70
|
+
async def send_reminder(user_id: int, message: str):
|
|
71
|
+
# Логика отправки напоминания
|
|
72
|
+
return {"status": "sent"}
|
|
73
|
+
|
|
74
|
+
# Запуск бота
|
|
75
|
+
async def main():
|
|
76
|
+
bot = BotBuilder("my-bot")
|
|
77
|
+
await bot.build()
|
|
78
|
+
await bot.start()
|
|
79
|
+
|
|
80
|
+
if __name__ == "__main__":
|
|
81
|
+
asyncio.run(main())
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Требования
|
|
85
|
+
|
|
86
|
+
- Python 3.9+
|
|
87
|
+
- OpenAI API ключ
|
|
88
|
+
- Telegram Bot Token
|
|
89
|
+
- Supabase проект
|
|
90
|
+
|
|
91
|
+
## Лицензия
|
|
92
|
+
|
|
93
|
+
MIT
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Бот best-valera - создан с помощью Smart Bot Factory
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
1
|
import asyncio
|
|
7
2
|
|
|
8
3
|
from smart_bot_factory.router import Router
|
|
@@ -19,7 +14,7 @@ supabase_client = SupabaseClient("best-valera")
|
|
|
19
14
|
# ОБРАБОТЧИКИ СОБЫТИЙ
|
|
20
15
|
# =============================================================================
|
|
21
16
|
|
|
22
|
-
@router.event_handler("
|
|
17
|
+
@router.event_handler("example_event")
|
|
23
18
|
async def handle_example_event(user_id: int, event_data: str):
|
|
24
19
|
"""Пример обработчика события"""
|
|
25
20
|
# Отправляем подтверждение пользователю
|
|
@@ -37,7 +32,7 @@ async def handle_example_event(user_id: int, event_data: str):
|
|
|
37
32
|
# ВРЕМЕННЫЕ ЗАДАЧИ ДЛЯ ОДНОГО ПОЛЬЗОВАТЕЛЯ
|
|
38
33
|
# =============================================================================
|
|
39
34
|
|
|
40
|
-
@router.schedule_task("send_reminder")
|
|
35
|
+
@router.schedule_task("send_reminder", delay="1h")
|
|
41
36
|
async def send_user_reminder(user_id: int, reminder_text: str):
|
|
42
37
|
"""Отправляет напоминание пользователю"""
|
|
43
38
|
await send_message_by_human(
|
|
@@ -54,61 +49,15 @@ async def send_user_reminder(user_id: int, reminder_text: str):
|
|
|
54
49
|
# ГЛОБАЛЬНЫЕ ОБРАБОТЧИКИ (для всех пользователей)
|
|
55
50
|
# =============================================================================
|
|
56
51
|
|
|
57
|
-
@router.global_handler("mass_notification", notify=True)
|
|
52
|
+
@router.global_handler("mass_notification", delay="1h", notify=True)
|
|
58
53
|
async def send_global_announcement(announcement_text: str):
|
|
59
54
|
"""Отправляет анонс всем пользователям бота"""
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if not supabase_client:
|
|
67
|
-
logger.error("❌ Supabase клиент не найден для глобальной рассылки")
|
|
68
|
-
return {"status": "error", "message": "Supabase клиент не найден"}
|
|
69
|
-
|
|
70
|
-
try:
|
|
71
|
-
# Получаем всех пользователей из БД с учетом bot_id (изоляция данных)
|
|
72
|
-
users_response = supabase_client.client.table('sales_users').select(
|
|
73
|
-
'telegram_id'
|
|
74
|
-
).eq('bot_id', supabase_client.bot_id).execute()
|
|
75
|
-
|
|
76
|
-
if not users_response.data:
|
|
77
|
-
logger.warning("⚠️ Пользователи не найдены для глобальной рассылки")
|
|
78
|
-
return {"status": "no_users", "message": "Пользователи не найдены"}
|
|
79
|
-
|
|
80
|
-
total_users = len(users_response.data)
|
|
81
|
-
logger.info(f"👥 Найдено {total_users} пользователей для рассылки")
|
|
82
|
-
|
|
83
|
-
# Отправляем сообщение каждому пользователю
|
|
84
|
-
sent_count = 0
|
|
85
|
-
failed_count = 0
|
|
86
|
-
|
|
87
|
-
for user in users_response.data:
|
|
88
|
-
try:
|
|
89
|
-
await send_message_by_human(
|
|
90
|
-
user_id=user['telegram_id'],
|
|
91
|
-
message_text=f"📢 {announcement_text}"
|
|
92
|
-
)
|
|
93
|
-
sent_count += 1
|
|
94
|
-
# Небольшая задержка между отправками
|
|
95
|
-
await asyncio.sleep(0.1)
|
|
96
|
-
|
|
97
|
-
except Exception as e:
|
|
98
|
-
logger.error(f"❌ Ошибка отправки пользователю {user['telegram_id']}: {e}")
|
|
99
|
-
failed_count += 1
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
"status": "completed",
|
|
103
|
-
"sent_count": sent_count,
|
|
104
|
-
"failed_count": failed_count,
|
|
105
|
-
"total_users": total_users,
|
|
106
|
-
"message": f"Рассылка завершена: {sent_count} отправлено, {failed_count} ошибок"
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
except Exception as e:
|
|
110
|
-
logger.error(f"❌ Критическая ошибка глобальной рассылки: {e}")
|
|
111
|
-
return {"status": "error", "message": str(e)}
|
|
55
|
+
|
|
56
|
+
await send_message_to_users_by_stage(
|
|
57
|
+
stage="introduction",
|
|
58
|
+
message_text=announcement_text,
|
|
59
|
+
bot_id="best-valera"
|
|
60
|
+
)
|
|
112
61
|
|
|
113
62
|
# =============================================================================
|
|
114
63
|
# ОСНОВНАЯ ФУНКЦИЯ
|
|
@@ -73,8 +73,6 @@ id этапа бери из stages
|
|
|
73
73
|
ТРЕБОВАНИЯ К формату:
|
|
74
74
|
- Всегда используй кавычки для строк
|
|
75
75
|
- Если в инструкциях явно не указано, что надо выслать какое-то событие, отсылай пустой массив []
|
|
76
|
-
- Если надо выслать какое либо событие и в инструкции написано запустить через какое то время, то в поле инфо нужно вывести число в СЕКУНДАХ
|
|
77
|
-
- Также в событиях связанных со временем может быть дополнительная информация, например инфо='30|Привет пользователь!' - 30 это время в секундах после | доп информация
|
|
78
76
|
- Если в инструкциях явно не указано, что надо вставить в служебную информацию какой-то файл(ы) или каталоги, отсылай пустой массив
|
|
79
77
|
|
|
80
78
|
ФАЙЛЫ:
|
|
@@ -128,6 +126,8 @@ id этапа бери из stages
|
|
|
128
126
|
<stage id="introduction">
|
|
129
127
|
на данном этапе выясни его имя, а также кем он работает и профиль его компании. после этого переходи к этапу consult.
|
|
130
128
|
если он уже в первом сообщении дал эту информацию - не переспрашивай.
|
|
129
|
+
|
|
130
|
+
Когда пользователь вписал свое имя впиши событие - тип=send_reminder, инфо=afdf, тип=mass_notification, инфо=ghbdtn
|
|
131
131
|
</stage>
|
|
132
132
|
|
|
133
133
|
<stage id="consult">
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
scenarios:
|
|
2
|
+
- name: "Быстрое решение по участию"
|
|
3
|
+
steps:
|
|
4
|
+
- user_input: "Привет, срочно нужна информация о конференции"
|
|
5
|
+
expected_keywords: ["привет", "информация", "конференци"]
|
|
6
|
+
forbidden_keywords: ["не спешите"]
|
|
7
|
+
|
|
8
|
+
- user_input: "Завтра улетаю в командировку, успею зарегистрироваться?"
|
|
9
|
+
expected_keywords: ["успеете", "регистрация", "быстро"]
|
|
10
|
+
forbidden_keywords: ["поздно", "не успеете"]
|
|
11
|
+
|
|
12
|
+
- name: "Студент медвуза интересуется будущим"
|
|
13
|
+
steps:
|
|
14
|
+
- user_input: "Здравствуйте, я студент 5 курса медуниверситета"
|
|
15
|
+
expected_keywords: ["здравствуйте", "студент", "медицин"]
|
|
16
|
+
forbidden_keywords: ["рано для вас"]
|
|
17
|
+
|
|
18
|
+
- user_input: "Стоит ли уже сейчас думать о бизнесе в медицине?"
|
|
19
|
+
expected_keywords: ["стоит", "перспектив", "будущее"]
|
|
20
|
+
forbidden_keywords: ["рано думать"]
|
|
21
|
+
|
|
22
|
+
- user_input: "Есть ли льготы для студентов?"
|
|
23
|
+
expected_keywords: ["льготы", "студент", "скидк"]
|
|
24
|
+
forbidden_keywords: ["полная стоимость"]
|
|
25
|
+
|
|
26
|
+
- name: "Иностранный врач в России"
|
|
27
|
+
steps:
|
|
28
|
+
- user_input: "Hello, I am foreign doctor working in Moscow"
|
|
29
|
+
expected_keywords: ["hello", "добро пожаловать", "moscow"]
|
|
30
|
+
forbidden_keywords: ["только на русском"]
|
|
31
|
+
|
|
32
|
+
- user_input: "Is conference in English or Russian language?"
|
|
33
|
+
expected_keywords: ["language", "english", "translation"]
|
|
34
|
+
forbidden_keywords: ["только русский"]
|
|
35
|
+
|
|
36
|
+
- user_input: "I want to understand Russian medical business"
|
|
37
|
+
expected_keywords: ["business", "russian", "understand"]
|
|
38
|
+
forbidden_keywords: ["сложно будет"]
|
|
39
|
+
|
|
40
|
+
- name: "Пенсионер-врач ищет активность"
|
|
41
|
+
steps:
|
|
42
|
+
- user_input: "Добрый день, я врач на пенсии уже 3 года"
|
|
43
|
+
expected_keywords: ["добрый день", "пенси", "врач"]
|
|
44
|
+
forbidden_keywords: ["не актуально"]
|
|
45
|
+
|
|
46
|
+
- user_input: "Хочу быть в курсе современных тенденций"
|
|
47
|
+
expected_keywords: ["современн", "тенденци", "актуальн"]
|
|
48
|
+
forbidden_keywords: ["устарело"]
|
|
49
|
+
|
|
50
|
+
- user_input: "Подходит ли конференция для неработающих врачей?"
|
|
51
|
+
expected_keywords: ["подходит", "для всех", "врачей"]
|
|
52
|
+
forbidden_keywords: ["только для практикующих"]
|
|
53
|
+
|
|
54
|
+
- name: "Технический директор медцентра"
|
|
55
|
+
steps:
|
|
56
|
+
- user_input: "Здравствуйте, я отвечаю за IT в медицинском центре"
|
|
57
|
+
expected_keywords: ["здравствуйте", "it", "медицинск"]
|
|
58
|
+
forbidden_keywords: ["не ваша тема"]
|
|
59
|
+
|
|
60
|
+
- user_input: "Есть ли секции по цифровизации медицины?"
|
|
61
|
+
expected_keywords: ["цифровизация", "технологи", "it"]
|
|
62
|
+
forbidden_keywords: ["только бизнес"]
|
|
63
|
+
|
|
64
|
+
- user_input: "Интересуют телемедицина и электронные карты"
|
|
65
|
+
expected_keywords: ["телемедицина", "электронн", "карты"]
|
|
66
|
+
forbidden_keywords: ["не рассматриваем"]
|
|
@@ -73,8 +73,6 @@ id этапа бери из stages
|
|
|
73
73
|
ТРЕБОВАНИЯ К формату:
|
|
74
74
|
- Всегда используй кавычки для строк
|
|
75
75
|
- Если в инструкциях явно не указано, что надо выслать какое-то событие, отсылай пустой массив []
|
|
76
|
-
- Если надо выслать какое либо событие и в инструкции написано запустить через какое то время, то в поле инфо нужно вывести число в СЕКУНДАХ
|
|
77
|
-
- Также в событиях связанных со временем может быть дополнительная информация, например инфо='30|Привет пользователь!' - 30 это время в секундах после | доп информация
|
|
78
76
|
- Если в инструкциях явно не указано, что надо вставить в служебную информацию какой-то файл(ы) или каталоги, отсылай пустой массив
|
|
79
77
|
|
|
80
78
|
ФАЙЛЫ:
|
|
@@ -128,8 +126,6 @@ id этапа бери из stages
|
|
|
128
126
|
<stage id="introduction">
|
|
129
127
|
на данном этапе выясни его имя, а также кем он работает и профиль его компании. после этого переходи к этапу consult.
|
|
130
128
|
если он уже в первом сообщении дал эту информацию - не переспрашивай.
|
|
131
|
-
|
|
132
|
-
Когда узнаешь имя пользователя, добавь событие тип='имя', в инфо добавь имя пользователя
|
|
133
129
|
</stage>
|
|
134
130
|
|
|
135
131
|
<stage id="consult">
|
|
@@ -137,8 +133,6 @@ id этапа бери из stages
|
|
|
137
133
|
если видишь, что особо вопросов больше не осталось переходи на этап offer.
|
|
138
134
|
будь краток, пиши по делу и только ключевую информацию. избегай длинных сообщений.
|
|
139
135
|
НЕ надо в первом же сообщении вываливать инфомацию из FAQ, пиши покороче.d
|
|
140
|
-
|
|
141
|
-
Если пользователь просит перевсти на консультацию добавь событие - тип=mass_notification запусти через минуту
|
|
142
136
|
</stage>
|
|
143
137
|
|
|
144
138
|
<stage id="offer">
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
scenarios:
|
|
2
|
+
- name: "Быстрое решение по участию"
|
|
3
|
+
steps:
|
|
4
|
+
- user_input: "Привет, срочно нужна информация о конференции"
|
|
5
|
+
expected_keywords: ["привет", "информация", "конференци"]
|
|
6
|
+
forbidden_keywords: ["не спешите"]
|
|
7
|
+
|
|
8
|
+
- user_input: "Завтра улетаю в командировку, успею зарегистрироваться?"
|
|
9
|
+
expected_keywords: ["успеете", "регистрация", "быстро"]
|
|
10
|
+
forbidden_keywords: ["поздно", "не успеете"]
|
|
11
|
+
|
|
12
|
+
- name: "Студент медвуза интересуется будущим"
|
|
13
|
+
steps:
|
|
14
|
+
- user_input: "Здравствуйте, я студент 5 курса медуниверситета"
|
|
15
|
+
expected_keywords: ["здравствуйте", "студент", "медицин"]
|
|
16
|
+
forbidden_keywords: ["рано для вас"]
|
|
17
|
+
|
|
18
|
+
- user_input: "Стоит ли уже сейчас думать о бизнесе в медицине?"
|
|
19
|
+
expected_keywords: ["стоит", "перспектив", "будущее"]
|
|
20
|
+
forbidden_keywords: ["рано думать"]
|
|
21
|
+
|
|
22
|
+
- user_input: "Есть ли льготы для студентов?"
|
|
23
|
+
expected_keywords: ["льготы", "студент", "скидк"]
|
|
24
|
+
forbidden_keywords: ["полная стоимость"]
|
|
25
|
+
|
|
26
|
+
- name: "Иностранный врач в России"
|
|
27
|
+
steps:
|
|
28
|
+
- user_input: "Hello, I am foreign doctor working in Moscow"
|
|
29
|
+
expected_keywords: ["hello", "добро пожаловать", "moscow"]
|
|
30
|
+
forbidden_keywords: ["только на русском"]
|
|
31
|
+
|
|
32
|
+
- user_input: "Is conference in English or Russian language?"
|
|
33
|
+
expected_keywords: ["language", "english", "translation"]
|
|
34
|
+
forbidden_keywords: ["только русский"]
|
|
35
|
+
|
|
36
|
+
- user_input: "I want to understand Russian medical business"
|
|
37
|
+
expected_keywords: ["business", "russian", "understand"]
|
|
38
|
+
forbidden_keywords: ["сложно будет"]
|
|
39
|
+
|
|
40
|
+
- name: "Пенсионер-врач ищет активность"
|
|
41
|
+
steps:
|
|
42
|
+
- user_input: "Добрый день, я врач на пенсии уже 3 года"
|
|
43
|
+
expected_keywords: ["добрый день", "пенси", "врач"]
|
|
44
|
+
forbidden_keywords: ["не актуально"]
|
|
45
|
+
|
|
46
|
+
- user_input: "Хочу быть в курсе современных тенденций"
|
|
47
|
+
expected_keywords: ["современн", "тенденци", "актуальн"]
|
|
48
|
+
forbidden_keywords: ["устарело"]
|
|
49
|
+
|
|
50
|
+
- user_input: "Подходит ли конференция для неработающих врачей?"
|
|
51
|
+
expected_keywords: ["подходит", "для всех", "врачей"]
|
|
52
|
+
forbidden_keywords: ["только для практикующих"]
|
|
53
|
+
|
|
54
|
+
- name: "Технический директор медцентра"
|
|
55
|
+
steps:
|
|
56
|
+
- user_input: "Здравствуйте, я отвечаю за IT в медицинском центре"
|
|
57
|
+
expected_keywords: ["здравствуйте", "it", "медицинск"]
|
|
58
|
+
forbidden_keywords: ["не ваша тема"]
|
|
59
|
+
|
|
60
|
+
- user_input: "Есть ли секции по цифровизации медицины?"
|
|
61
|
+
expected_keywords: ["цифровизация", "технологи", "it"]
|
|
62
|
+
forbidden_keywords: ["только бизнес"]
|
|
63
|
+
|
|
64
|
+
- user_input: "Интересуют телемедицина и электронные карты"
|
|
65
|
+
expected_keywords: ["телемедицина", "электронн", "карты"]
|
|
66
|
+
forbidden_keywords: ["не рассматриваем"]
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "smart-bot-factory"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.8"
|
|
4
4
|
description = "Библиотека для создания умных чат-ботов"
|
|
5
5
|
authors = [
|
|
6
|
-
{name = "Kopatych", email = "
|
|
6
|
+
{name = "Kopatych", email = "kopatych@example.com"}
|
|
7
7
|
]
|
|
8
8
|
keywords = ["chatbot", "telegram", "openai", "supabase", "cli"]
|
|
9
9
|
classifiers = [
|
|
@@ -408,15 +408,10 @@ def list_bots_in_bots_folder() -> list:
|
|
|
408
408
|
|
|
409
409
|
def create_bot_template(bot_id: str) -> str:
|
|
410
410
|
"""Создает шаблон основного файла бота"""
|
|
411
|
-
return f'''
|
|
412
|
-
"""
|
|
413
|
-
Бот {bot_id} - создан с помощью Smart Bot Factory
|
|
414
|
-
"""
|
|
415
|
-
|
|
416
|
-
import asyncio
|
|
411
|
+
return f'''import asyncio
|
|
417
412
|
|
|
418
413
|
from smart_bot_factory.router import Router
|
|
419
|
-
from smart_bot_factory.message import send_message_by_human
|
|
414
|
+
from smart_bot_factory.message import send_message_by_human, send_message_to_users_by_stage
|
|
420
415
|
from smart_bot_factory.supabase import SupabaseClient
|
|
421
416
|
from smart_bot_factory.creation import BotBuilder
|
|
422
417
|
|
|
@@ -447,7 +442,7 @@ async def handle_example_event(user_id: int, event_data: str):
|
|
|
447
442
|
# ВРЕМЕННЫЕ ЗАДАЧИ ДЛЯ ОДНОГО ПОЛЬЗОВАТЕЛЯ
|
|
448
443
|
# =============================================================================
|
|
449
444
|
|
|
450
|
-
@router.schedule_task("send_reminder")
|
|
445
|
+
@router.schedule_task("send_reminder", delay="1h")
|
|
451
446
|
async def send_user_reminder(user_id: int, reminder_text: str):
|
|
452
447
|
"""Отправляет напоминание пользователю"""
|
|
453
448
|
await send_message_by_human(
|
|
@@ -464,61 +459,15 @@ async def send_user_reminder(user_id: int, reminder_text: str):
|
|
|
464
459
|
# ГЛОБАЛЬНЫЕ ОБРАБОТЧИКИ (для всех пользователей)
|
|
465
460
|
# =============================================================================
|
|
466
461
|
|
|
467
|
-
@router.global_handler("mass_notification", notify=True)
|
|
462
|
+
@router.global_handler("mass_notification", delay="1h", notify=True)
|
|
468
463
|
async def send_global_announcement(announcement_text: str):
|
|
469
464
|
"""Отправляет анонс всем пользователям бота"""
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
if not supabase_client:
|
|
477
|
-
logger.error("❌ Supabase клиент не найден для глобальной рассылки")
|
|
478
|
-
return {{"status": "error", "message": "Supabase клиент не найден"}}
|
|
479
|
-
|
|
480
|
-
try:
|
|
481
|
-
# Получаем всех пользователей из БД с учетом bot_id (изоляция данных)
|
|
482
|
-
users_response = supabase_client.client.table('sales_users').select(
|
|
483
|
-
'telegram_id'
|
|
484
|
-
).eq('bot_id', supabase_client.bot_id).execute()
|
|
485
|
-
|
|
486
|
-
if not users_response.data:
|
|
487
|
-
logger.warning("⚠️ Пользователи не найдены для глобальной рассылки")
|
|
488
|
-
return {{"status": "no_users", "message": "Пользователи не найдены"}}
|
|
489
|
-
|
|
490
|
-
total_users = len(users_response.data)
|
|
491
|
-
logger.info(f"👥 Найдено {{total_users}} пользователей для рассылки")
|
|
492
|
-
|
|
493
|
-
# Отправляем сообщение каждому пользователю
|
|
494
|
-
sent_count = 0
|
|
495
|
-
failed_count = 0
|
|
496
|
-
|
|
497
|
-
for user in users_response.data:
|
|
498
|
-
try:
|
|
499
|
-
await send_message_by_human(
|
|
500
|
-
user_id=user['telegram_id'],
|
|
501
|
-
message_text=f"📢 {{announcement_text}}"
|
|
502
|
-
)
|
|
503
|
-
sent_count += 1
|
|
504
|
-
# Небольшая задержка между отправками
|
|
505
|
-
await asyncio.sleep(0.1)
|
|
506
|
-
|
|
507
|
-
except Exception as e:
|
|
508
|
-
logger.error(f"❌ Ошибка отправки пользователю {{user['telegram_id']}}: {{e}}")
|
|
509
|
-
failed_count += 1
|
|
510
|
-
|
|
511
|
-
return {{
|
|
512
|
-
"status": "completed",
|
|
513
|
-
"sent_count": sent_count,
|
|
514
|
-
"failed_count": failed_count,
|
|
515
|
-
"total_users": total_users,
|
|
516
|
-
"message": f"Рассылка завершена: {{sent_count}} отправлено, {{failed_count}} ошибок"
|
|
517
|
-
}}
|
|
518
|
-
|
|
519
|
-
except Exception as e:
|
|
520
|
-
logger.error(f"❌ Критическая ошибка глобальной рассылки: {{e}}")
|
|
521
|
-
return {{"status": "error", "message": str(e)}}
|
|
465
|
+
|
|
466
|
+
await send_message_to_users_by_stage(
|
|
467
|
+
stage="introduction",
|
|
468
|
+
message_text=announcement_text,
|
|
469
|
+
bot_id="{bot_id}"
|
|
470
|
+
)
|
|
522
471
|
|
|
523
472
|
# =============================================================================
|
|
524
473
|
# ОСНОВНАЯ ФУНКЦИЯ
|