smart-bot-factory 0.2.5__tar.gz → 0.2.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 (104) hide show
  1. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/PKG-INFO +1 -1
  2. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/best-valera.py +248 -248
  3. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/pyproject.toml +1 -1
  4. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/creation/bot_builder.py +41 -4
  5. smart_bot_factory-0.2.6/smart_bot_factory/utils/__init__.py +10 -0
  6. smart_bot_factory-0.2.6/smart_bot_factory/utils/user_prompt_loader.py +56 -0
  7. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/uv.lock +1 -1
  8. smart_bot_factory-0.2.5/smart_bot_factory/utils/__init__.py +0 -9
  9. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/.claude/settings.local.json +0 -0
  10. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/.env.example +0 -0
  11. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.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" +0 -0
  12. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.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" +0 -0
  13. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/.github/workflows/ci.yml +0 -0
  14. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/.github/workflows/publish-private.yml +0 -0
  15. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/.github/workflows/publish.yml +0 -0
  16. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/.gitignore +0 -0
  17. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/.python-version +0 -0
  18. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/CLIENTS_USAGE.md +0 -0
  19. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/Dockerfile +0 -0
  20. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/LICENSE +0 -0
  21. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/README.md +0 -0
  22. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/1sales_context.txt +0 -0
  23. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/2product_info.txt +0 -0
  24. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/3objection_handling.txt +0 -0
  25. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/final_instructions.txt +0 -0
  26. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/help_message.txt +0 -0
  27. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/welcome_message.txt +0 -0
  28. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/best-valera/tests/quick_scenarios.yaml +0 -0
  29. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/best-valera/tests/realistic_scenarios.yaml +0 -0
  30. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/best-valera/tests/scenario_examples.yaml +0 -0
  31. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/best-valera/welcome_files/welcome_file_msg.txt +0 -0
  32. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.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
  33. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/valera/prompts/2product_info.txt +0 -0
  34. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/valera/prompts/3objection_handling.txt +0 -0
  35. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/valera/prompts/final_instructions.txt +0 -0
  36. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/valera/prompts/help_message.txt +0 -0
  37. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/valera/prompts/welcome_message.txt +0 -0
  38. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/valera/tests/quick_scenarios.yaml +0 -0
  39. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/valera/tests/realistic_scenarios.yaml +0 -0
  40. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/valera/tests/scenario_examples.yaml +0 -0
  41. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/bots/valera/welcome_files/welcome_file_msg.txt +0 -0
  42. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.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
  43. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/configs/valera/cats//320/224/320/276/320/263/320/276/320/262/320/276/321/200.pdf" +0 -0
  44. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/configs/valera/cats//320/272/320/276/320/275/320/270.jpg" +0 -0
  45. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/configs/valera/cats//320/272/320/276/321/202.jpg" +0 -0
  46. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/configs/valera/cats//320/273/320/265/321/201.jpg" +0 -0
  47. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/configs/valera/tests/fixes_elina.yaml +0 -0
  48. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/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
  49. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/create_tag.sh +0 -0
  50. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/docker-compose.yml +0 -0
  51. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/env.example +0 -0
  52. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/requirements.txt +0 -0
  53. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/save_backup.sh +0 -0
  54. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/save_fixes.sh +0 -0
  55. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/__init__.py +0 -0
  56. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/__init__.py +0 -0
  57. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/admin_logic.py +0 -0
  58. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/admin_manager.py +0 -0
  59. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/admin_migration.sql +0 -0
  60. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/admin_tester.py +0 -0
  61. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/timeout_checker.py +0 -0
  62. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/analytics/analytics_manager.py +0 -0
  63. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/cli.py +0 -0
  64. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/config.py +0 -0
  65. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/1sales_context.txt +0 -0
  66. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/2product_info.txt +0 -0
  67. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/3objection_handling.txt +0 -0
  68. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/final_instructions.txt +0 -0
  69. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/help_message.txt +0 -0
  70. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/welcome_message.txt +0 -0
  71. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064229.txt +0 -0
  72. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064335.txt +0 -0
  73. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064638.txt +0 -0
  74. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/tests/quick_scenarios.yaml +0 -0
  75. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/tests/realistic_scenarios.yaml +0 -0
  76. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/tests/scenario_examples.yaml +0 -0
  77. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/welcome_file/welcome_file_msg.txt +0 -0
  78. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.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
  79. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/core/bot_utils.py +0 -0
  80. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/core/conversation_manager.py +0 -0
  81. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/core/decorators.py +0 -0
  82. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/core/message_sender.py +0 -0
  83. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/core/router.py +0 -0
  84. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/core/router_manager.py +0 -0
  85. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/core/states.py +0 -0
  86. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/core/telegram_router.py +0 -0
  87. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/creation/__init__.py +0 -0
  88. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/creation/bot_testing.py +0 -0
  89. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/event/__init__.py +0 -0
  90. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/handlers/handlers.py +0 -0
  91. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/integrations/openai_client.py +0 -0
  92. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/integrations/supabase_client.py +0 -0
  93. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/message/__init__.py +0 -0
  94. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/router/__init__.py +0 -0
  95. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/setup_checker.py +0 -0
  96. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/supabase/__init__.py +0 -0
  97. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/supabase/client.py +0 -0
  98. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/table/database_structure.sql +0 -0
  99. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/table/schema.sql +0 -0
  100. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/utils/debug_routing.py +0 -0
  101. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/utils/prompt_loader.py +0 -0
  102. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/smart_bot_factory/utm_link_generator.py +0 -0
  103. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/system_prompt_example.txt +0 -0
  104. {smart_bot_factory-0.2.5 → smart_bot_factory-0.2.6}/valera.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smart-bot-factory
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: Библиотека для создания умных чат-ботов
5
5
  Author-email: Kopatych <kopatych@example.com>
6
6
  License: MIT
@@ -1,248 +1,248 @@
1
- import asyncio
2
- import logging
3
-
4
- from smart_bot_factory.router import EventRouter, TelegramRouter
5
- from smart_bot_factory.message import send_message_by_human, send_message_to_users_by_stage, send_message
6
- from smart_bot_factory.supabase import SupabaseClient
7
- from smart_bot_factory.creation import BotBuilder
8
-
9
- logger = logging.getLogger(__name__)
10
-
11
- # =============================================================================
12
- # СОЗДАНИЕ РОУТЕРОВ
13
- # =============================================================================
14
-
15
- # Роутер для событий (бизнес-логика)
16
- event_router = EventRouter("best-valera_events")
17
-
18
- # Роутер для Telegram (команды и сообщения)
19
- telegram_router_1 = TelegramRouter("best-valera_telegram")
20
- telegram_router_2 = TelegramRouter("best-valera_telegram_2")
21
-
22
- supabase_client = SupabaseClient("best-valera")
23
-
24
- # =============================================================================
25
- # ИНИЦИАЛИЗАЦИЯ BOT BUILDER (нужен для декоратора on_start)
26
- # =============================================================================
27
-
28
- bot_builder = BotBuilder("best-valera")
29
-
30
- # =============================================================================
31
- # TELEGRAM ОБРАБОТЧИКИ (используем прямой aiogram API)
32
- # =============================================================================
33
-
34
- from aiogram import F
35
- from aiogram.filters import Command
36
- from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
37
- from aiogram.fsm.context import FSMContext
38
-
39
- # =============================================================================
40
- # ОБРАБОТЧИК on_start (вызывается после стандартного /start)
41
- # =============================================================================
42
-
43
- @bot_builder.on_start
44
- async def custom_start_handler(user_id: int, session_id: str, message: Message, state: FSMContext):
45
- """
46
- Вызывается после стандартной логики /start
47
- Здесь можно отправить дополнительные сообщения, кнопки и т.д.
48
- """
49
- # Пример: отправляем сообщение с кнопками
50
- keyboard = InlineKeyboardMarkup(inline_keyboard=[
51
- [InlineKeyboardButton(text="📖 Каталог", callback_data="catalog")],
52
- [InlineKeyboardButton(text="💰 Цены", callback_data="prices")],
53
- [InlineKeyboardButton(text="📞 Связаться", callback_data="contact")]
54
- ])
55
-
56
- await message.answer(
57
- "🎯 Что вас интересует?",
58
- reply_markup=keyboard
59
- )
60
-
61
- # =============================================================================
62
- # ХУКИ ДЛЯ КАСТОМИЗАЦИИ ОБРАБОТКИ СООБЩЕНИЙ
63
- # =============================================================================
64
-
65
- # ХУК 1: Валидация сообщений
66
- @bot_builder.validate_message
67
- async def validate_service_names(message, supabase_client):
68
- """Проверяем корректность названий услуг"""
69
- # Пример: блокируем неправильные названия
70
- incorrect_names = ["массаш", "педекюр", "макияш"]
71
-
72
- if message.text:
73
- for incorrect in incorrect_names:
74
- if incorrect in message.text.lower():
75
- await message.answer(
76
- f"❗ Возможно, вы имели в виду другую услугу?\n"
77
- f"Пожалуйста, уточните название"
78
- )
79
- return False # Прерываем обработку AI
80
-
81
- return True # Продолжаем обработку
82
-
83
- # ХУК 2: Обогащение промпта
84
- @bot_builder.enrich_prompt
85
- async def add_client_info_to_prompt(system_prompt, user_id, session_id, supabase_client):
86
- """Добавляем информацию о клиенте в промпт"""
87
- try:
88
- session = await supabase_client.get_active_session(user_id)
89
-
90
- if session and session.get('metadata'):
91
- phone = session['metadata'].get('phone')
92
- name = session['metadata'].get('confirmed_name') or session['metadata'].get('telegram_name')
93
-
94
- if phone:
95
- client_info = f"\n\nИНФОРМАЦИЯ О КЛИЕНТЕ:\n- Телефон: {phone}"
96
- if name:
97
- client_info += f"\n- Имя: {name}"
98
- client_info += "\n\n⚠️ ВАЖНО: При создании записи используй ЭТОТ телефон и имя!"
99
-
100
- return system_prompt + client_info
101
- except Exception as e:
102
- logger.error(f"Ошибка обогащения промпта: {e}")
103
-
104
- return system_prompt
105
-
106
- # ХУК 3: Обогащение контекста (например, данные из внешнего API)
107
- @bot_builder.enrich_context
108
- async def add_external_api_data(messages, user_id, session_id):
109
- """Добавляем данные из внешних систем"""
110
- # Пример: можно добавить расписание из YClients, данные из CRM и т.д.
111
- # messages.append({
112
- # "role": "system",
113
- # "content": "Реальное доступное время: ..."
114
- # })
115
- return messages
116
-
117
- # ХУК 4: Обработка ответа AI
118
- @bot_builder.process_response
119
- async def add_promo_to_price_response(response_text, ai_metadata, user_id):
120
- """Добавляем промо-код к ответам о ценах"""
121
- if "цен" in response_text.lower() or "стоимост" in response_text.lower():
122
- response_text += "\n\n🎁 Промокод FIRST10 для скидки 10% на первый визит!"
123
-
124
- return response_text, ai_metadata
125
-
126
- # ХУК 5: Фильтр отправки
127
- @bot_builder.filter_send
128
- async def allow_all_messages(user_id, response_text):
129
- """Разрешаем все сообщения (можно добавить блокировку по условию)"""
130
- # Пример: блокировка во время обработки
131
- # if is_processing(user_id):
132
- # return False
133
- return True
134
-
135
- @telegram_router_1.router.message(Command("price", "цена"))
136
- async def handle_price_command(message: Message, state: FSMContext):
137
- """Обработчик команды /price"""
138
- await message.answer(
139
- "💰 Наши цены:\n\n"
140
- "📦 Базовый пакет - 1000₽\n"
141
- "📦 Стандартный - 2000₽\n"
142
- "📦 Премиум - 5000₽"
143
- )
144
-
145
- @telegram_router_2.router.message(F.text & (F.text.lower().contains("цена") | F.text.lower().contains("стоимость")))
146
- async def handle_price_question(message: Message, state: FSMContext):
147
- """Обработчик вопросов о цене"""
148
- await message.answer("💡 Напишите /price чтобы увидеть актуальные цены")
149
-
150
- # Обработчики callback'ов от кнопок в on_start
151
- @telegram_router_1.router.callback_query(F.data == "catalog")
152
- async def handle_catalog(callback: CallbackQuery, state: FSMContext):
153
- """Обработка кнопки Каталог"""
154
- await callback.answer()
155
-
156
- # Пример: используем send_message с файлами
157
- await send_message(
158
- message=callback.message,
159
- text="📖 Вот наш каталог товаров:\n\n1. Товар 1\n2. Товар 2\n3. Товар 3",
160
- supabase_client=supabase_client,
161
- files_list=[], # Можно добавить файлы: ["catalog.pdf"]
162
- parse_mode="Markdown"
163
- )
164
-
165
- @telegram_router_1.router.callback_query(F.data == "prices")
166
- async def handle_prices(callback: CallbackQuery, state: FSMContext):
167
- """Обработка кнопки Цены"""
168
- await callback.answer()
169
- await callback.message.answer("💰 Наши цены:\n\n📦 Базовый - 1000₽\n📦 Премиум - 5000₽")
170
-
171
- @telegram_router_1.router.callback_query(F.data == "contact")
172
- async def handle_contact(callback: CallbackQuery, state: FSMContext):
173
- """Обработка кнопки Связаться"""
174
- await callback.answer()
175
- await callback.message.answer("📞 Свяжитесь с нами:\n\nТелефон: +7 (999) 123-45-67\nEmail: info@example.com")
176
-
177
- # =============================================================================
178
- # ОБРАБОТЧИКИ СОБЫТИЙ (бизнес-логика)
179
- # =============================================================================
180
-
181
- @event_router.event_handler("example_event")
182
- async def handle_example_event(user_id: int, event_data: str):
183
- """Пример обработчика события"""
184
- await send_message_by_human(
185
- user_id=user_id,
186
- message_text=f"✅ Событие обработано! Данные: {event_data}"
187
- )
188
-
189
- return {
190
- "status": "success",
191
- "message": "Событие обработано"
192
- }
193
-
194
- # =============================================================================
195
- # ВРЕМЕННЫЕ ЗАДАЧИ ДЛЯ ОДНОГО ПОЛЬЗОВАТЕЛЯ
196
- # =============================================================================
197
-
198
- @event_router.schedule_task("send_reminder", delay="1h")
199
- async def send_user_reminder(user_id: int, reminder_text: str):
200
- """Отправляет напоминание пользователю"""
201
- await send_message_by_human(
202
- user_id=user_id,
203
- message_text=f"🔔 Напоминание: {reminder_text}"
204
- )
205
-
206
- return {
207
- "status": "reminder_sent",
208
- "message": f"Напоминание отправлено пользователю {user_id}"
209
- }
210
-
211
- # =============================================================================
212
- # ГЛОБАЛЬНЫЕ ОБРАБОТЧИКИ (для всех пользователей)
213
- # =============================================================================
214
-
215
- @event_router.global_handler("mass_notification", delay="1h", notify=True)
216
- async def send_global_announcement(announcement_text: str):
217
- """Отправляет анонс всем пользователям бота"""
218
-
219
- await send_message_to_users_by_stage(
220
- stage="introduction",
221
- message_text=announcement_text,
222
- bot_id="best-valera"
223
- )
224
-
225
- # =============================================================================
226
- # ОСНОВНАЯ ФУНКЦИЯ
227
- # =============================================================================
228
-
229
- async def main():
230
- """Основная функция запуска бота"""
231
- try:
232
- # bot_builder уже создан выше (для декоратора @bot_builder.on_start)
233
-
234
- # Регистрируем роутеры ПЕРЕД сборкой (можно по одному или несколько сразу)
235
- bot_builder.register_routers(event_router) # Роутеры событий
236
- bot_builder.register_telegram_routers(telegram_router_1, telegram_router_2) # Telegram роутеры
237
-
238
- await bot_builder.build()
239
-
240
- # Запускаем бота
241
- await bot_builder.start()
242
-
243
- except Exception as e:
244
- print(f"❌ Ошибка запуска бота: {e}")
245
- raise
246
-
247
- if __name__ == "__main__":
248
- asyncio.run(main())
1
+ import asyncio
2
+ import logging
3
+
4
+ from smart_bot_factory.router import EventRouter, TelegramRouter
5
+ from smart_bot_factory.message import send_message_by_human, send_message_to_users_by_stage, send_message
6
+ from smart_bot_factory.supabase import SupabaseClient
7
+ from smart_bot_factory.creation import BotBuilder
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ # =============================================================================
12
+ # СОЗДАНИЕ РОУТЕРОВ
13
+ # =============================================================================
14
+
15
+ # Роутер для событий (бизнес-логика)
16
+ event_router = EventRouter("best-valera_events")
17
+
18
+ # Роутер для Telegram (команды и сообщения)
19
+ telegram_router_1 = TelegramRouter("best-valera_telegram")
20
+ telegram_router_2 = TelegramRouter("best-valera_telegram_2")
21
+
22
+ supabase_client = SupabaseClient("best-valera")
23
+
24
+ # =============================================================================
25
+ # ИНИЦИАЛИЗАЦИЯ BOT BUILDER (нужен для декоратора on_start)
26
+ # =============================================================================
27
+
28
+ bot_builder = BotBuilder("best-valera")
29
+
30
+ # =============================================================================
31
+ # TELEGRAM ОБРАБОТЧИКИ (используем прямой aiogram API)
32
+ # =============================================================================
33
+
34
+ from aiogram import F
35
+ from aiogram.filters import Command
36
+ from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
37
+ from aiogram.fsm.context import FSMContext
38
+
39
+ # =============================================================================
40
+ # ОБРАБОТЧИК on_start (вызывается после стандартного /start)
41
+ # =============================================================================
42
+
43
+ @bot_builder.on_start
44
+ async def custom_start_handler(user_id: int, session_id: str, message: Message, state: FSMContext):
45
+ """
46
+ Вызывается после стандартной логики /start
47
+ Здесь можно отправить дополнительные сообщения, кнопки и т.д.
48
+ """
49
+ # Пример: отправляем сообщение с кнопками
50
+ keyboard = InlineKeyboardMarkup(inline_keyboard=[
51
+ [InlineKeyboardButton(text="📖 Каталог", callback_data="catalog")],
52
+ [InlineKeyboardButton(text="💰 Цены", callback_data="prices")],
53
+ [InlineKeyboardButton(text="📞 Связаться", callback_data="contact")]
54
+ ])
55
+
56
+ await message.answer(
57
+ "🎯 Что вас интересует?",
58
+ reply_markup=keyboard
59
+ )
60
+
61
+ # =============================================================================
62
+ # ХУКИ ДЛЯ КАСТОМИЗАЦИИ ОБРАБОТКИ СООБЩЕНИЙ
63
+ # =============================================================================
64
+
65
+ # ХУК 1: Валидация сообщений
66
+ @bot_builder.validate_message
67
+ async def validate_service_names(message, supabase_client):
68
+ """Проверяем корректность названий услуг"""
69
+ # Пример: блокируем неправильные названия
70
+ incorrect_names = ["массаш", "педекюр", "макияш"]
71
+
72
+ if message.text:
73
+ for incorrect in incorrect_names:
74
+ if incorrect in message.text.lower():
75
+ await message.answer(
76
+ f"❗ Возможно, вы имели в виду другую услугу?\n"
77
+ f"Пожалуйста, уточните название"
78
+ )
79
+ return False # Прерываем обработку AI
80
+
81
+ return True # Продолжаем обработку
82
+
83
+ # ХУК 2: Обогащение промпта
84
+ @bot_builder.enrich_prompt
85
+ async def add_client_info_to_prompt(system_prompt, user_id, session_id, supabase_client):
86
+ """Добавляем информацию о клиенте в промпт"""
87
+ try:
88
+ session = await supabase_client.get_active_session(user_id)
89
+
90
+ if session and session.get('metadata'):
91
+ phone = session['metadata'].get('phone')
92
+ name = session['metadata'].get('confirmed_name') or session['metadata'].get('telegram_name')
93
+
94
+ if phone:
95
+ client_info = f"\n\nИНФОРМАЦИЯ О КЛИЕНТЕ:\n- Телефон: {phone}"
96
+ if name:
97
+ client_info += f"\n- Имя: {name}"
98
+ client_info += "\n\n⚠️ ВАЖНО: При создании записи используй ЭТОТ телефон и имя!"
99
+
100
+ return system_prompt + client_info
101
+ except Exception as e:
102
+ logger.error(f"Ошибка обогащения промпта: {e}")
103
+
104
+ return system_prompt
105
+
106
+ # ХУК 3: Обогащение контекста (например, данные из внешнего API)
107
+ @bot_builder.enrich_context
108
+ async def add_external_api_data(messages, user_id, session_id):
109
+ """Добавляем данные из внешних систем"""
110
+ # Пример: можно добавить расписание из YClients, данные из CRM и т.д.
111
+ # messages.append({
112
+ # "role": "system",
113
+ # "content": "Реальное доступное время: ..."
114
+ # })
115
+ return messages
116
+
117
+ # ХУК 4: Обработка ответа AI
118
+ @bot_builder.process_response
119
+ async def add_promo_to_price_response(response_text, ai_metadata, user_id):
120
+ """Добавляем промо-код к ответам о ценах"""
121
+ if "цен" in response_text.lower() or "стоимост" in response_text.lower():
122
+ response_text += "\n\n🎁 Промокод FIRST10 для скидки 10% на первый визит!"
123
+
124
+ return response_text, ai_metadata
125
+
126
+ # ХУК 5: Фильтр отправки
127
+ @bot_builder.filter_send
128
+ async def allow_all_messages(user_id, response_text):
129
+ """Разрешаем все сообщения (можно добавить блокировку по условию)"""
130
+ # Пример: блокировка во время обработки
131
+ # if is_processing(user_id):
132
+ # return False
133
+ return True
134
+
135
+ @telegram_router_1.router.message(Command("price", "цена"))
136
+ async def handle_price_command(message: Message, state: FSMContext):
137
+ """Обработчик команды /price"""
138
+ await message.answer(
139
+ "💰 Наши цены:\n\n"
140
+ "📦 Базовый пакет - 1000₽\n"
141
+ "📦 Стандартный - 2000₽\n"
142
+ "📦 Премиум - 5000₽"
143
+ )
144
+
145
+ @telegram_router_2.router.message(F.text & (F.text.lower().contains("цена") | F.text.lower().contains("стоимость")))
146
+ async def handle_price_question(message: Message, state: FSMContext):
147
+ """Обработчик вопросов о цене"""
148
+ await message.answer("💡 Напишите /price чтобы увидеть актуальные цены")
149
+
150
+ # Обработчики callback'ов от кнопок в on_start
151
+ @telegram_router_1.router.callback_query(F.data == "catalog")
152
+ async def handle_catalog(callback: CallbackQuery, state: FSMContext):
153
+ """Обработка кнопки Каталог"""
154
+ await callback.answer()
155
+
156
+ # Пример: используем send_message с файлами
157
+ await send_message(
158
+ message=callback.message,
159
+ text="📖 Вот наш каталог товаров:\n\n1. Товар 1\n2. Товар 2\n3. Товар 3",
160
+ supabase_client=supabase_client,
161
+ files_list=[], # Можно добавить файлы: ["catalog.pdf"]
162
+ parse_mode="Markdown"
163
+ )
164
+
165
+ @telegram_router_1.router.callback_query(F.data == "prices")
166
+ async def handle_prices(callback: CallbackQuery, state: FSMContext):
167
+ """Обработка кнопки Цены"""
168
+ await callback.answer()
169
+ await callback.message.answer("💰 Наши цены:\n\n📦 Базовый - 1000₽\n📦 Премиум - 5000₽")
170
+
171
+ @telegram_router_1.router.callback_query(F.data == "contact")
172
+ async def handle_contact(callback: CallbackQuery, state: FSMContext):
173
+ """Обработка кнопки Связаться"""
174
+ await callback.answer()
175
+ await callback.message.answer("📞 Свяжитесь с нами:\n\nТелефон: +7 (999) 123-45-67\nEmail: info@example.com")
176
+
177
+ # =============================================================================
178
+ # ОБРАБОТЧИКИ СОБЫТИЙ (бизнес-логика)
179
+ # =============================================================================
180
+
181
+ @event_router.event_handler("example_event")
182
+ async def handle_example_event(user_id: int, event_data: str):
183
+ """Пример обработчика события"""
184
+ await send_message_by_human(
185
+ user_id=user_id,
186
+ message_text=f"✅ Событие обработано! Данные: {event_data}"
187
+ )
188
+
189
+ return {
190
+ "status": "success",
191
+ "message": "Событие обработано"
192
+ }
193
+
194
+ # =============================================================================
195
+ # ВРЕМЕННЫЕ ЗАДАЧИ ДЛЯ ОДНОГО ПОЛЬЗОВАТЕЛЯ
196
+ # =============================================================================
197
+
198
+ @event_router.schedule_task("send_reminder", delay="1h")
199
+ async def send_user_reminder(user_id: int, reminder_text: str):
200
+ """Отправляет напоминание пользователю"""
201
+ await send_message_by_human(
202
+ user_id=user_id,
203
+ message_text=f"🔔 Напоминание: {reminder_text}"
204
+ )
205
+
206
+ return {
207
+ "status": "reminder_sent",
208
+ "message": f"Напоминание отправлено пользователю {user_id}"
209
+ }
210
+
211
+ # =============================================================================
212
+ # ГЛОБАЛЬНЫЕ ОБРАБОТЧИКИ (для всех пользователей)
213
+ # =============================================================================
214
+
215
+ @event_router.global_handler("mass_notification", delay="1h", notify=True)
216
+ async def send_global_announcement(announcement_text: str):
217
+ """Отправляет анонс всем пользователям бота"""
218
+
219
+ await send_message_to_users_by_stage(
220
+ stage="introduction",
221
+ message_text=announcement_text,
222
+ bot_id="best-valera"
223
+ )
224
+
225
+ # =============================================================================
226
+ # ОСНОВНАЯ ФУНКЦИЯ
227
+ # =============================================================================
228
+
229
+ async def main():
230
+ """Основная функция запуска бота"""
231
+ try:
232
+ # bot_builder уже создан выше (для декоратора @bot_builder.on_start)
233
+
234
+ # Регистрируем роутеры ПЕРЕД сборкой (можно по одному или несколько сразу)
235
+ bot_builder.register_routers(event_router) # Роутеры событий
236
+ bot_builder.register_telegram_routers(telegram_router_1, telegram_router_2) # Telegram роутеры
237
+
238
+ await bot_builder.build()
239
+
240
+ # Запускаем бота
241
+ await bot_builder.start()
242
+
243
+ except Exception as e:
244
+ print(f"❌ Ошибка запуска бота: {e}")
245
+ raise
246
+
247
+ if __name__ == "__main__":
248
+ asyncio.run(main())
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "smart-bot-factory"
3
- version = "0.2.5"
3
+ version = "0.2.6"
4
4
  description = "Библиотека для создания умных чат-ботов"
5
5
  authors = [
6
6
  {name = "Kopatych", email = "kopatych@example.com"}
@@ -55,6 +55,9 @@ class BotBuilder:
55
55
  self._response_processors: List = [] # Обработка ответа AI
56
56
  self._send_filters: List = [] # Фильтры перед отправкой пользователю
57
57
 
58
+ # Кастомный PromptLoader
59
+ self._custom_prompt_loader = None
60
+
58
61
  # Флаги инициализации
59
62
  self._initialized = False
60
63
 
@@ -175,10 +178,16 @@ class BotBuilder:
175
178
  else:
176
179
  logger.info(f"✅ Router Manager уже был создан ранее")
177
180
 
178
- # Prompt Loader
179
- self.prompt_loader = PromptLoader(
180
- prompts_dir=self.config.PROMT_FILES_DIR
181
- )
181
+ # Prompt Loader (используем кастомный если установлен)
182
+ if self._custom_prompt_loader:
183
+ self.prompt_loader = self._custom_prompt_loader
184
+ logger.info(f"✅ Используется кастомный Prompt Loader: {type(self.prompt_loader).__name__}")
185
+ else:
186
+ self.prompt_loader = PromptLoader(
187
+ prompts_dir=self.config.PROMT_FILES_DIR
188
+ )
189
+ logger.info(f"✅ Используется стандартный Prompt Loader")
190
+
182
191
  await self.prompt_loader.validate_prompts()
183
192
  logger.info(f"✅ Prompt Loader инициализирован")
184
193
 
@@ -365,6 +374,34 @@ class BotBuilder:
365
374
  """Получает список обработчиков on_start"""
366
375
  return self._start_handlers.copy()
367
376
 
377
+ def set_prompt_loader(self, prompt_loader):
378
+ """
379
+ Устанавливает кастомный PromptLoader
380
+
381
+ Должен быть вызван ДО build()
382
+
383
+ Args:
384
+ prompt_loader: Экземпляр PromptLoader или его наследника (например UserPromptLoader)
385
+
386
+ Example:
387
+ from smart_bot_factory.utils import UserPromptLoader
388
+
389
+ # Использовать UserPromptLoader с автопоиском prompts_dir
390
+ custom_loader = UserPromptLoader("my-bot")
391
+ bot_builder.set_prompt_loader(custom_loader)
392
+
393
+ # Или кастомный наследник
394
+ class MyPromptLoader(UserPromptLoader):
395
+ def __init__(self, bot_id):
396
+ super().__init__(bot_id)
397
+ self.extra_file = self.prompts_dir / 'extra.txt'
398
+
399
+ my_loader = MyPromptLoader("my-bot")
400
+ bot_builder.set_prompt_loader(my_loader)
401
+ """
402
+ self._custom_prompt_loader = prompt_loader
403
+ logger.info(f"✅ Установлен кастомный PromptLoader: {type(prompt_loader).__name__}")
404
+
368
405
  # ========== ХУКИ ДЛЯ КАСТОМИЗАЦИИ ОБРАБОТКИ СООБЩЕНИЙ ==========
369
406
 
370
407
  def validate_message(self, handler):
@@ -0,0 +1,10 @@
1
+ """
2
+ Utils модули smart_bot_factory
3
+ """
4
+
5
+
6
+ from .user_prompt_loader import UserPromptLoader
7
+
8
+ __all__ = [ # Базовый класс (для библиотеки)
9
+ 'UserPromptLoader', # Для пользователей (автопоиск prompts_dir)
10
+ ]
@@ -0,0 +1,56 @@
1
+ """
2
+ UserPromptLoader - упрощенный PromptLoader для пользователей библиотеки
3
+ с автоматическим поиском prompts_dir от корня проекта
4
+ """
5
+
6
+ import logging
7
+ from pathlib import Path
8
+ from .prompt_loader import PromptLoader
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class UserPromptLoader(PromptLoader):
14
+ """
15
+ PromptLoader для пользователей библиотеки с автоматическим поиском prompts_dir
16
+
17
+ Автоматически находит папку prompts для указанного бота от корня проекта
18
+ Наследуется от базового PromptLoader - все методы доступны
19
+ """
20
+
21
+ def __init__(self, bot_id: str, prompts_subdir: str = "prompts"):
22
+ """
23
+ Инициализация загрузчика промптов с автоматическим поиском
24
+
25
+ Args:
26
+ bot_id: Идентификатор бота
27
+ prompts_subdir: Подпапка с промптами (по умолчанию "prompts")
28
+
29
+ Example:
30
+ # Автоматически найдет bots/my-bot/prompts
31
+ loader = UserPromptLoader("my-bot")
32
+
33
+ # Или кастомную подпапку
34
+ loader = UserPromptLoader("my-bot", "custom_prompts")
35
+
36
+ # Наследование для кастомизации
37
+ class MyLoader(UserPromptLoader):
38
+ def __init__(self, bot_id):
39
+ super().__init__(bot_id)
40
+ # Добавить свою логику
41
+ self.extra_file = self.prompts_dir / 'extra.txt'
42
+ """
43
+ from project_root_finder import root
44
+
45
+ # Автоматически определяем путь к промптам
46
+ prompts_dir = root / "bots" / bot_id / prompts_subdir
47
+
48
+ if not prompts_dir.exists():
49
+ logger.warning(f"⚠️ Папка промптов не найдена: {prompts_dir}")
50
+ logger.warning(f" Создайте папку или проверьте bot_id")
51
+
52
+ # Вызываем базовую инициализацию
53
+ super().__init__(str(prompts_dir))
54
+
55
+ logger.info(f"✅ UserPromptLoader создан для bot_id '{bot_id}': {prompts_dir}")
56
+
@@ -1259,7 +1259,7 @@ wheels = [
1259
1259
 
1260
1260
  [[package]]
1261
1261
  name = "smart-bot-factory"
1262
- version = "0.2.4"
1262
+ version = "0.2.5"
1263
1263
  source = { editable = "." }
1264
1264
  dependencies = [
1265
1265
  { name = "aiofiles" },
@@ -1,9 +0,0 @@
1
- """
2
- Utils модули smart_bot_factory
3
- """
4
-
5
- from ..integrations.supabase_client import SupabaseClient
6
- from ..utils.prompt_loader import PromptLoader
7
- from ..utils.debug_routing import setup_debug_handlers
8
-
9
- __all__ = ['SupabaseClient', 'PromptLoader', 'setup_debug_handlers']