smart-bot-factory 0.3.4__tar.gz → 0.3.6__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.

Files changed (90) hide show
  1. smart_bot_factory-0.3.6/.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 +20 -0
  2. smart_bot_factory-0.3.6/.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 +26 -0
  3. smart_bot_factory-0.3.6/.github/workflows/ci.yml +59 -0
  4. smart_bot_factory-0.3.6/.github/workflows/publish-private.yml +34 -0
  5. smart_bot_factory-0.3.6/.github/workflows/publish.yml +31 -0
  6. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/.gitignore +0 -5
  7. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/PKG-INFO +233 -22
  8. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/README.md +232 -19
  9. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/best-valera.py +37 -10
  10. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/best-valera/prompts/final_instructions.txt +1 -1
  11. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/pyproject.toml +1 -3
  12. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/core/bot_utils.py +43 -10
  13. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/core/decorators.py +116 -22
  14. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/core/message_sender.py +11 -2
  15. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/core/router.py +59 -8
  16. smart_bot_factory-0.3.6/smart_bot_factory/dashboard/__init__.py +5 -0
  17. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/handlers/handlers.py +17 -4
  18. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/integrations/supabase_client.py +4 -3
  19. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/utils/prompt_loader.py +12 -8
  20. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/uv.lock +1 -38
  21. smart_bot_factory-0.3.4/smart_bot_factory/admin/admin_migration.sql +0 -136
  22. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/.python-version +0 -0
  23. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/LICENSE +0 -0
  24. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/best-valera/prompts/1sales_context.txt +0 -0
  25. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/best-valera/prompts/2product_info.txt +0 -0
  26. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/best-valera/prompts/3objection_handling.txt +0 -0
  27. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/best-valera/prompts/help_message.txt +0 -0
  28. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/best-valera/prompts/welcome_message.txt +0 -0
  29. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/best-valera/tests/quick_scenarios.yaml +0 -0
  30. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/best-valera/tests/realistic_scenarios.yaml +0 -0
  31. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/best-valera/tests/scenario_examples.yaml +0 -0
  32. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/best-valera/welcome_files/welcome_file_msg.txt +0 -0
  33. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/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
  34. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/valera/prompts/2product_info.txt +0 -0
  35. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/valera/prompts/3objection_handling.txt +0 -0
  36. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/valera/prompts/final_instructions.txt +0 -0
  37. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/valera/prompts/help_message.txt +0 -0
  38. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/valera/prompts/welcome_message.txt +0 -0
  39. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/valera/tests/quick_scenarios.yaml +0 -0
  40. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/valera/tests/realistic_scenarios.yaml +0 -0
  41. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/valera/tests/scenario_examples.yaml +0 -0
  42. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/bots/valera/welcome_files/welcome_file_msg.txt +0 -0
  43. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/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
  44. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/publish.py +0 -0
  45. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/__init__.py +0 -0
  46. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/admin/__init__.py +0 -0
  47. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/admin/admin_events.py +0 -0
  48. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/admin/admin_logic.py +0 -0
  49. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/admin/admin_manager.py +0 -0
  50. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/admin/admin_tester.py +0 -0
  51. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/admin/timeout_checker.py +0 -0
  52. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/aiogram_calendar/__init__.py +0 -0
  53. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/aiogram_calendar/common.py +0 -0
  54. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/aiogram_calendar/dialog_calendar.py +0 -0
  55. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/aiogram_calendar/schemas.py +0 -0
  56. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/aiogram_calendar/simple_calendar.py +0 -0
  57. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/analytics/analytics_manager.py +0 -0
  58. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/cli.py +0 -0
  59. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/config.py +0 -0
  60. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/prompts/1sales_context.txt +0 -0
  61. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/prompts/2product_info.txt +0 -0
  62. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/prompts/3objection_handling.txt +0 -0
  63. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/prompts/final_instructions.txt +0 -0
  64. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/prompts/help_message.txt +0 -0
  65. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/prompts/welcome_message.txt +0 -0
  66. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064229.txt +0 -0
  67. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064335.txt +0 -0
  68. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064638.txt +0 -0
  69. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/tests/quick_scenarios.yaml +0 -0
  70. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/tests/realistic_scenarios.yaml +0 -0
  71. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/tests/scenario_examples.yaml +0 -0
  72. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/configs/growthmed-october-24/welcome_file/welcome_file_msg.txt +0 -0
  73. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/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
  74. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/core/conversation_manager.py +0 -0
  75. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/core/router_manager.py +0 -0
  76. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/core/states.py +0 -0
  77. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/creation/__init__.py +0 -0
  78. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/creation/bot_builder.py +0 -0
  79. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/creation/bot_testing.py +0 -0
  80. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/event/__init__.py +0 -0
  81. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/integrations/openai_client.py +0 -0
  82. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/message/__init__.py +0 -0
  83. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/router/__init__.py +0 -0
  84. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/setup_checker.py +0 -0
  85. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/supabase/__init__.py +0 -0
  86. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/supabase/client.py +0 -0
  87. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/utils/__init__.py +0 -0
  88. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/utils/debug_routing.py +0 -0
  89. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/utils/user_prompt_loader.py +0 -0
  90. {smart_bot_factory-0.3.4 → smart_bot_factory-0.3.6}/smart_bot_factory/utm_link_generator.py +0 -0
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: "✨ Запрос функции"
3
+ about: Предложить новую функцию или улучшение
4
+ title: ''
5
+ labels: enhancement
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ ## 🎯 Описание функции
11
+ Что вы хотите добавить/улучшить?
12
+
13
+ ## 💡 Мотивация
14
+ Какую проблему это решит?
15
+
16
+ ## 📋 Детали реализации
17
+ Как вы видите это решение?
18
+
19
+ ## 🔄 Альтернативы
20
+ Рассматривали ли другие варианты?
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: "\U0001F41B Баг репорт"
3
+ about: Сообщить об ошибке
4
+ title: ''
5
+ labels: bug
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ ## 🐛 Описание проблемы
11
+ Опишите что пошло не так
12
+
13
+ ## 🔄 Как воспроизвести
14
+ 1. Пользователь написал...
15
+ 2. Бот ответил...
16
+ 3. Произошла ошибка...
17
+
18
+ ## ✅ Ожидаемое поведение
19
+ Что должно было произойти
20
+
21
+ ## 📱 Окружение
22
+ - **Bot ID:** (например, growthmed-october-24)
23
+ - **Время:** (когда произошло)
24
+ - **User ID:** (если известен)
25
+
26
+ ## 📋 Логи
@@ -0,0 +1,59 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.12", "3.13"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install -e .
28
+
29
+ - name: Run tests
30
+ run: |
31
+ pytest --cov=smart_bot_factory tests/
32
+
33
+ - name: Upload coverage to Codecov
34
+ uses: codecov/codecov-action@v4
35
+ with:
36
+ token: ${{ secrets.CODECOV_TOKEN }}
37
+ fail_ci_if_error: true
38
+
39
+ lint:
40
+ runs-on: ubuntu-latest
41
+
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+
45
+ - name: Set up Python
46
+ uses: actions/setup-python@v5
47
+ with:
48
+ python-version: "3.12"
49
+
50
+ - name: Install dependencies
51
+ run: |
52
+ python -m pip install --upgrade pip
53
+ pip install flake8 black isort
54
+
55
+ - name: Check code style
56
+ run: |
57
+ flake8 src/smart_bot_factory tests
58
+ black --check src/smart_bot_factory tests
59
+ isort --check-only src/smart_bot_factory tests
@@ -0,0 +1,34 @@
1
+ name: Publish to GitHub Packages
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: read
12
+ packages: write
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v4
19
+ with:
20
+ python-version: "3.9"
21
+
22
+ - name: Install build tools
23
+ run: |
24
+ python -m pip install --upgrade pip
25
+ pip install build twine
26
+
27
+ - name: Build package
28
+ run: python -m build
29
+
30
+ - name: Publish to GitHub Packages
31
+ env:
32
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33
+ run: |
34
+ python -m twine upload --repository-url https://maven.pkg.github.com/${{ github.repository }} dist/*
@@ -0,0 +1,31 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+
13
+ - name: Set up Python
14
+ uses: actions/setup-python@v4
15
+ with:
16
+ python-version: "3.9"
17
+
18
+ - name: Install build tools
19
+ run: |
20
+ python -m pip install --upgrade pip
21
+ pip install build twine
22
+
23
+ - name: Build package
24
+ run: python -m build
25
+
26
+ - name: Publish to PyPI
27
+ env:
28
+ TWINE_USERNAME: __token__
29
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
30
+ run: |
31
+ twine upload dist/*
@@ -213,8 +213,3 @@ cython_debug/
213
213
  marimo/_static/
214
214
  marimo/_lsp/
215
215
  __marimo__/
216
-
217
- # Temporary event files
218
- temp_event_files/
219
- temp_with_msg/
220
- temp_after_msg/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smart-bot-factory
3
- Version: 0.3.4
3
+ Version: 0.3.6
4
4
  Summary: Библиотека для создания умных чат-ботов
5
5
  Author-email: Kopatych <eserov73@gmail.com>
6
6
  License: MIT
@@ -21,12 +21,10 @@ Classifier: Topic :: Communications :: Chat
21
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Requires-Python: >=3.9
23
23
  Requires-Dist: aiofiles>=23.0.0
24
- Requires-Dist: aiogram-media-group>=0.5.1
25
24
  Requires-Dist: aiogram>=3.4.1
26
25
  Requires-Dist: click>=8.0.0
27
26
  Requires-Dist: openai>=1.12.0
28
27
  Requires-Dist: project-root-finder>=1.9
29
- Requires-Dist: python-dateutil>=2.9.0.post0
30
28
  Requires-Dist: python-dotenv>=1.0.1
31
29
  Requires-Dist: pytz>=2023.3
32
30
  Requires-Dist: pyyaml>=6.0.2
@@ -46,6 +44,7 @@ Description-Content-Type: text/markdown
46
44
  - [event_handler](#event_handler---обработчики-событий)
47
45
  - [schedule_task](#schedule_task---запланированные-задачи)
48
46
  - [global_handler](#global_handler---глобальные-обработчики)
47
+ - [Dashboard Info](#-dashboard-info---отправка-данных-в-дашборд)
49
48
  - [Хуки для кастомизации](#-хуки-для-кастомизации)
50
49
  - [Telegram роутеры](#-telegram-роутеры)
51
50
  - [Расширенные возможности](#-расширенные-возможности)
@@ -189,9 +188,10 @@ sbf link
189
188
 
190
189
  ```python
191
190
  @event_router.event_handler(
192
- event_type: str, # Тип события
193
- notify: bool = False, # Уведомлять админов
194
- once_only: bool = True # Выполнять только 1 раз
191
+ event_type: str, # Тип события
192
+ notify: bool = False, # Уведомлять админов
193
+ once_only: bool = True, # Выполнять только 1 раз
194
+ send_ai_response: bool = True # Отправлять ответ от ИИ
195
195
  )
196
196
  async def handler(user_id: int, event_data: str):
197
197
  # Ваш код
@@ -203,6 +203,7 @@ async def handler(user_id: int, event_data: str):
203
203
  - **`event_type`** (обязательный) - Уникальное имя события
204
204
  - **`notify`** (по умолчанию `False`) - Отправлять уведомление админам после выполнения
205
205
  - **`once_only`** (по умолчанию `True`) - Если `True`, событие выполнится только 1 раз для пользователя
206
+ - **`send_ai_response`** (по умолчанию `True`) - Если `False`, ИИ НЕ отправит сообщение после выполнения обработчика
206
207
 
207
208
  **Как работает:**
208
209
 
@@ -237,6 +238,16 @@ async def handle_question(user_id: int, question: str):
237
238
  """Обрабатывает вопросы (может быть много)"""
238
239
  # Логика обработки
239
240
  return {"status": "answered"}
241
+
242
+ # БЕЗ отправки ответа от ИИ
243
+ @event_router.event_handler("silent_event", send_ai_response=False)
244
+ async def handle_silent(user_id: int, event_data: str):
245
+ """
246
+ Выполняет логику БЕЗ отправки сообщения от ИИ
247
+ Используйте когда хотите только собрать данные без ответа пользователю
248
+ """
249
+ await send_message_by_human(user_id, "✅ Данные сохранены")
250
+ return {"status": "saved"}
240
251
  ```
241
252
 
242
253
  ---
@@ -249,12 +260,13 @@ async def handle_question(user_id: int, question: str):
249
260
 
250
261
  ```python
251
262
  @event_router.schedule_task(
252
- task_name: str, # Название задачи
253
- delay: Union[str, int], # Задержка: "1h 30m" или секунды
254
- notify: bool = False, # Уведомлять админов
255
- smart_check: bool = True, # Умная проверка активности
256
- once_only: bool = True, # Выполнять только 1 раз
257
- event_type: Union[str, Callable] = None # Источник времени события
263
+ task_name: str, # Название задачи
264
+ delay: Union[str, int], # Задержка: "1h 30m" или секунды
265
+ notify: bool = False, # Уведомлять админов
266
+ smart_check: bool = True, # Умная проверка активности
267
+ once_only: bool = True, # Выполнять только 1 раз
268
+ event_type: Union[str, Callable] = None, # Источник времени события
269
+ send_ai_response: bool = True # Отправлять ответ от ИИ
258
270
  )
259
271
  async def handler(user_id: int, user_data: str):
260
272
  # Ваш код
@@ -275,6 +287,7 @@ async def handler(user_id: int, user_data: str):
275
287
  - **`event_type`** (опционально) - Источник времени события:
276
288
  - **Строка**: `"appointment_booking"` - ищет событие в БД и вычисляет время
277
289
  - **Функция**: `async def(user_id, user_data) -> datetime` - кастомная логика
290
+ - **`send_ai_response`** (по умолчанию `True`) - Если `False`, ИИ НЕ отправит сообщение после выполнения задачи
278
291
 
279
292
  **Формула времени с `event_type`:**
280
293
 
@@ -364,11 +377,12 @@ async def important_reminder(user_id: int, text: str):
364
377
 
365
378
  ```python
366
379
  @event_router.global_handler(
367
- handler_type: str, # Тип обработчика
368
- delay: Union[str, int], # Задержка
369
- notify: bool = False, # Уведомлять админов
370
- once_only: bool = True, # Выполнять только 1 раз
371
- event_type: Union[str, Callable] = None # Источник времени
380
+ handler_type: str, # Тип обработчика
381
+ delay: Union[str, int], # Задержка
382
+ notify: bool = False, # Уведомлять админов
383
+ once_only: bool = True, # Выполнять только 1 раз
384
+ event_type: Union[str, Callable] = None, # Источник времени
385
+ send_ai_response: bool = True # Отправлять ответ от ИИ
372
386
  )
373
387
  async def handler(handler_data: str):
374
388
  # Ваш код
@@ -422,6 +436,173 @@ async def notify_promo_ending(handler_data: str):
422
436
 
423
437
  ---
424
438
 
439
+ ## 📊 Dashboard Info - Отправка данных в дашборд
440
+
441
+ **Назначение:** Позволяет отправлять информацию о событиях в дашборд (таблица `scheduled_events`, столбец `info_dashboard`) для аналитики и мониторинга.
442
+
443
+ ### Как работает
444
+
445
+ 1. Обработчик события возвращает результат с полем `'info'`
446
+ 2. Система автоматически извлекает это поле и записывает в `info_dashboard` таблицы
447
+ 3. Функция `prepare_dashboard_info` автоматически:
448
+ - Получает `username` из таблицы `sales_users`
449
+ - Форматирует строку с подстановкой данных
450
+ - Добавляет московское время (UTC+3)
451
+
452
+ ### Сигнатура
453
+
454
+ ```python
455
+ from smart_bot_factory.dashboard import prepare_dashboard_info
456
+
457
+ dashboard_data = await prepare_dashboard_info(
458
+ description_template: str, # Строка с {username}, например "{username} купил подписку"
459
+ title: str, # Заголовок для дашборда
460
+ user_id: int # Telegram ID пользователя
461
+ )
462
+ ```
463
+
464
+ **Возвращает:**
465
+
466
+ ```python
467
+ {
468
+ 'title': 'Заголовок',
469
+ 'description': '@username123 купил подписку', # С подстановкой реального username
470
+ 'created_at': '2025-10-18T15:30:45.123456+03:00' # Московское время
471
+ }
472
+ ```
473
+
474
+ ### Примеры использования
475
+
476
+ #### С event_handler
477
+
478
+ ```python
479
+ from smart_bot_factory.dashboard import prepare_dashboard_info
480
+
481
+ @event_router.event_handler("collect_phone", notify=True, once_only=True)
482
+ async def handle_phone_collection(user_id: int, phone_number: str):
483
+ """Сохраняет телефон клиента"""
484
+
485
+ # Ваша бизнес-логика
486
+ session = await supabase_client.get_active_session(user_id)
487
+ if session:
488
+ metadata = session.get('metadata', {})
489
+ metadata['phone'] = phone_number
490
+ await supabase_client.update_session_metadata(session['id'], metadata)
491
+
492
+ await send_message_by_human(
493
+ user_id=user_id,
494
+ message_text=f"✅ Спасибо! Ваш номер {phone_number} сохранен"
495
+ )
496
+
497
+ # 📊 Возвращаем результат С данными для дашборда
498
+ return {
499
+ "status": "success",
500
+ "phone": phone_number,
501
+ "info": await prepare_dashboard_info(
502
+ description_template="{username} оставил номер телефона",
503
+ title="Новый контакт",
504
+ user_id=user_id
505
+ )
506
+ }
507
+ ```
508
+
509
+ #### С schedule_task
510
+
511
+ ```python
512
+ @event_router.schedule_task("follow_up", delay="24h", smart_check=True)
513
+ async def send_follow_up(user_id: int, reminder_text: str):
514
+ """Напоминание через 24 часа"""
515
+
516
+ await send_message_by_human(
517
+ user_id=user_id,
518
+ message_text=f"👋 {reminder_text}"
519
+ )
520
+
521
+ # 📊 Работает и для задач!
522
+ return {
523
+ "status": "sent",
524
+ "type": "follow_up",
525
+ "info": await prepare_dashboard_info(
526
+ description_template="{username} получил напоминание",
527
+ title="Напоминание отправлено",
528
+ user_id=user_id
529
+ )
530
+ }
531
+ ```
532
+
533
+ #### БЕЗ дашборда
534
+
535
+ Если не нужно отправлять данные в дашборд - просто не добавляйте поле `'info'`:
536
+
537
+ ```python
538
+ @event_router.event_handler("collect_name", once_only=False)
539
+ async def handle_name_collection(user_id: int, client_name: str):
540
+ """БЕЗ дашборда - просто сохраняем имя"""
541
+
542
+ await send_message_by_human(
543
+ user_id=user_id,
544
+ message_text=f"✅ Спасибо! Ваше имя {client_name} сохранено"
545
+ )
546
+
547
+ # Возвращаем БЕЗ поля 'info' - дашборд останется пустым
548
+ return {"status": "success"}
549
+ ```
550
+
551
+ ### Что попадает в БД
552
+
553
+ **События С дашбордом:**
554
+
555
+ ```sql
556
+ SELECT * FROM scheduled_events WHERE id = '123';
557
+
558
+ id: 123
559
+ event_type: collect_phone
560
+ event_category: user_event
561
+ user_id: 12345
562
+ status: completed
563
+ result_data: {"status": "success", "phone": "+79001234567", "info": {...}}
564
+ info_dashboard: {
565
+ "title": "Новый контакт",
566
+ "description": "@username123 оставил номер телефона",
567
+ "created_at": "2025-10-18T15:30:45+03:00"
568
+ }
569
+ ```
570
+
571
+ **События БЕЗ дашборда:**
572
+
573
+ ```sql
574
+ SELECT * FROM scheduled_events WHERE id = '124';
575
+
576
+ id: 124
577
+ event_type: collect_name
578
+ event_category: user_event
579
+ user_id: 12345
580
+ status: completed
581
+ result_data: {"status": "success"}
582
+ info_dashboard: NULL ← Остается пустым
583
+ ```
584
+
585
+ ### Форматирование строк
586
+
587
+ Функция `prepare_dashboard_info` поддерживает подстановку `{username}`:
588
+
589
+ ```python
590
+ # Примеры шаблонов:
591
+ "{username} купил подписку на 1 год"
592
+ "{username} оставил контакт"
593
+ "{username} записался на консультацию"
594
+ "{username} задал вопрос о продукте"
595
+ "{username} завершил оплату"
596
+
597
+ # После подстановки:
598
+ "@user123 купил подписку на 1 год"
599
+ "@ivan_petrov оставил контакт"
600
+ ```
601
+
602
+ Если пользователь не найден в `sales_users` - будет использован fallback: `user_12345`
603
+
604
+ ---
605
+
425
606
  ## 🎣 Хуки для кастомизации
426
607
 
427
608
  Хуки позволяют внедрять свою логику в стандартную обработку сообщений без переписывания всей функции.
@@ -815,16 +996,46 @@ DEBUG_MODE=false
815
996
 
816
997
  ## 🎯 Сравнение декораторов
817
998
 
818
- | Декоратор | Когда выполняется | Для кого | Параметры |
819
- |-----------|-------------------|----------|-----------|
820
- | `@event_handler` | Немедленно | 1 пользователь | `event_type`, `notify`, `once_only` |
821
- | `@schedule_task` | Через время | 1 пользователь | `task_name`, `delay`, `event_type`, `smart_check`, `once_only`, `notify` |
822
- | `@global_handler` | Через время | Все пользователи | `handler_type`, `delay`, `event_type`, `once_only`, `notify` |
999
+ | Декоратор | Когда выполняется | Для кого | Ключевые параметры |
1000
+ |-----------|-------------------|----------|--------------------|
1001
+ | `@event_handler` | Немедленно | 1 пользователь | `event_type`, `notify`, `once_only`, `send_ai_response` |
1002
+ | `@schedule_task` | Через время | 1 пользователь | `task_name`, `delay`, `event_type`, `smart_check`, `once_only`, `notify`, `send_ai_response` |
1003
+ | `@global_handler` | Через время | Все пользователи | `handler_type`, `delay`, `event_type`, `once_only`, `notify`, `send_ai_response` |
823
1004
 
824
1005
  ---
825
1006
 
826
1007
  ## 🔑 Ключевые концепции
827
1008
 
1009
+ ### `send_ai_response=True`
1010
+
1011
+ Контролирует отправку сообщения от ИИ после выполнения обработчика:
1012
+
1013
+ - **`True`** (по умолчанию) - ИИ отправит сообщение пользователю после выполнения обработчика
1014
+ - **`False`** - ИИ НЕ отправит сообщение (используйте когда нужна только фоновая обработка или когда отправляете сообщение вручную)
1015
+
1016
+ **Когда использовать `send_ai_response=False`:**
1017
+
1018
+ - Когда нужно только собрать данные без ответа пользователю
1019
+ - Когда вы сами отправляете сообщение через `send_message_by_human()`
1020
+ - Для фоновых задач без взаимодействия с пользователем
1021
+
1022
+ ```python
1023
+ # ИИ отправит сообщение (по умолчанию)
1024
+ @event_router.event_handler("collect_phone")
1025
+ async def save_phone(user_id: int, phone: str):
1026
+ # Сохраняем телефон
1027
+ # ИИ автоматически отправит сообщение после выполнения
1028
+ return {"status": "success"}
1029
+
1030
+ # ИИ НЕ отправит сообщение
1031
+ @event_router.event_handler("collect_name", send_ai_response=False)
1032
+ async def save_name(user_id: int, name: str):
1033
+ # Сохраняем имя
1034
+ await send_message_by_human(user_id, f"✅ Имя {name} сохранено")
1035
+ # ИИ не будет отправлять свое сообщение
1036
+ return {"status": "success"}
1037
+ ```
1038
+
828
1039
  ### `once_only=True`
829
1040
 
830
1041
  Гарантирует выполнение события только 1 раз для пользователя: