smart-bot-factory 0.3.7__py3-none-any.whl → 0.3.9__py3-none-any.whl
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/admin/__init__.py +7 -7
- smart_bot_factory/admin/admin_events.py +483 -383
- smart_bot_factory/admin/admin_logic.py +234 -158
- smart_bot_factory/admin/admin_manager.py +68 -53
- smart_bot_factory/admin/admin_tester.py +46 -40
- smart_bot_factory/admin/timeout_checker.py +201 -153
- smart_bot_factory/aiogram_calendar/__init__.py +11 -3
- smart_bot_factory/aiogram_calendar/common.py +12 -18
- smart_bot_factory/aiogram_calendar/dialog_calendar.py +126 -64
- smart_bot_factory/aiogram_calendar/schemas.py +49 -28
- smart_bot_factory/aiogram_calendar/simple_calendar.py +94 -50
- smart_bot_factory/analytics/analytics_manager.py +414 -392
- smart_bot_factory/cli.py +204 -148
- smart_bot_factory/config.py +123 -102
- smart_bot_factory/core/bot_utils.py +474 -332
- smart_bot_factory/core/conversation_manager.py +287 -200
- smart_bot_factory/core/decorators.py +1200 -755
- smart_bot_factory/core/message_sender.py +287 -266
- smart_bot_factory/core/router.py +170 -100
- smart_bot_factory/core/router_manager.py +121 -83
- smart_bot_factory/core/states.py +4 -3
- smart_bot_factory/creation/__init__.py +1 -1
- smart_bot_factory/creation/bot_builder.py +320 -242
- smart_bot_factory/creation/bot_testing.py +440 -365
- smart_bot_factory/dashboard/__init__.py +1 -3
- smart_bot_factory/event/__init__.py +2 -7
- smart_bot_factory/handlers/handlers.py +676 -472
- smart_bot_factory/integrations/openai_client.py +218 -168
- smart_bot_factory/integrations/supabase_client.py +948 -637
- smart_bot_factory/message/__init__.py +18 -22
- smart_bot_factory/router/__init__.py +2 -2
- smart_bot_factory/setup_checker.py +162 -126
- smart_bot_factory/supabase/__init__.py +1 -1
- smart_bot_factory/supabase/client.py +631 -515
- smart_bot_factory/utils/__init__.py +2 -3
- smart_bot_factory/utils/debug_routing.py +38 -27
- smart_bot_factory/utils/prompt_loader.py +153 -120
- smart_bot_factory/utils/user_prompt_loader.py +55 -56
- smart_bot_factory/utm_link_generator.py +123 -116
- {smart_bot_factory-0.3.7.dist-info → smart_bot_factory-0.3.9.dist-info}/METADATA +3 -1
- smart_bot_factory-0.3.9.dist-info/RECORD +59 -0
- smart_bot_factory-0.3.7.dist-info/RECORD +0 -59
- {smart_bot_factory-0.3.7.dist-info → smart_bot_factory-0.3.9.dist-info}/WHEEL +0 -0
- {smart_bot_factory-0.3.7.dist-info → smart_bot_factory-0.3.9.dist-info}/entry_points.txt +0 -0
- {smart_bot_factory-0.3.7.dist-info → smart_bot_factory-0.3.9.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,136 +4,147 @@
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import logging
|
|
7
|
-
import sys
|
|
8
7
|
import os
|
|
8
|
+
import sys
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
from typing import
|
|
10
|
+
from typing import List, Optional, Tuple
|
|
11
11
|
|
|
12
|
-
from .config import Config
|
|
13
|
-
from .integrations.supabase_client import SupabaseClient
|
|
14
|
-
from .integrations.openai_client import OpenAIClient
|
|
15
|
-
from .utils.prompt_loader import PromptLoader
|
|
16
12
|
from .admin.admin_manager import AdminManager
|
|
17
|
-
from .core.conversation_manager import ConversationManager
|
|
18
13
|
from .analytics.analytics_manager import AnalyticsManager
|
|
14
|
+
from .config import Config
|
|
19
15
|
from .core.bot_utils import parse_ai_response
|
|
16
|
+
from .core.conversation_manager import ConversationManager
|
|
17
|
+
from .integrations.openai_client import OpenAIClient
|
|
18
|
+
from .integrations.supabase_client import SupabaseClient
|
|
19
|
+
from .utils.prompt_loader import PromptLoader
|
|
20
20
|
|
|
21
21
|
logger = logging.getLogger(__name__)
|
|
22
22
|
|
|
23
|
+
|
|
23
24
|
def setup_bot_environment(bot_name: str = "growthmed-october-24") -> Optional[Path]:
|
|
24
25
|
"""
|
|
25
26
|
Настраивает окружение для указанного бота с автоопределением BOT_ID
|
|
26
|
-
|
|
27
|
+
|
|
27
28
|
Args:
|
|
28
29
|
bot_name: Имя бота для настройки
|
|
29
|
-
|
|
30
|
+
|
|
30
31
|
Returns:
|
|
31
32
|
Optional[Path]: Путь к корневой директории проекта, если настройка успешна, None в случае ошибки
|
|
32
33
|
"""
|
|
33
34
|
root_dir = Path(os.getcwd()) # Используем текущую директорию как корневую
|
|
34
|
-
config_dir = root_dir /
|
|
35
|
-
|
|
35
|
+
config_dir = root_dir / "bots" / bot_name
|
|
36
|
+
|
|
36
37
|
if not config_dir.exists():
|
|
37
38
|
logger.error(f"❌ Папка конфигурации не найдена: {config_dir}")
|
|
38
|
-
logger.info(
|
|
39
|
-
bots_dir = root_dir /
|
|
39
|
+
logger.info(" Доступные боты:")
|
|
40
|
+
bots_dir = root_dir / "bots"
|
|
40
41
|
if bots_dir.exists():
|
|
41
42
|
for bot_dir in bots_dir.iterdir():
|
|
42
43
|
if bot_dir.is_dir():
|
|
43
44
|
logger.info(f" - {bot_dir.name}")
|
|
44
45
|
return None
|
|
45
|
-
|
|
46
|
+
|
|
46
47
|
# Устанавливаем BOT_ID из имени бота
|
|
47
|
-
os.environ[
|
|
48
|
+
os.environ["BOT_ID"] = bot_name
|
|
48
49
|
logger.info(f"🤖 Автоматически установлен BOT_ID: {bot_name}")
|
|
49
|
-
|
|
50
|
+
|
|
50
51
|
# Загружаем .env из конфигурации бота
|
|
51
|
-
env_file = config_dir /
|
|
52
|
+
env_file = config_dir / ".env"
|
|
52
53
|
if env_file.exists():
|
|
53
54
|
logger.info(f"🔧 Загружаем .env из: {env_file}")
|
|
54
55
|
from dotenv import load_dotenv
|
|
56
|
+
|
|
55
57
|
load_dotenv(env_file)
|
|
56
58
|
else:
|
|
57
59
|
logger.error(f"❌ Файл .env не найден: {env_file}")
|
|
58
60
|
return None
|
|
59
|
-
|
|
61
|
+
|
|
60
62
|
# Меняем рабочую директорию
|
|
61
63
|
os.chdir(str(config_dir))
|
|
62
64
|
logger.info(f"📁 Рабочая директория: {config_dir}")
|
|
63
|
-
|
|
65
|
+
|
|
64
66
|
return root_dir
|
|
65
67
|
|
|
68
|
+
|
|
66
69
|
async def check_config() -> Optional[Config]:
|
|
67
70
|
"""Проверяем конфигурацию с новыми админскими настройками"""
|
|
68
71
|
try:
|
|
69
72
|
config = Config()
|
|
70
|
-
|
|
73
|
+
|
|
71
74
|
logger.info("✅ Конфигурация загружена успешно")
|
|
72
|
-
logger.info(
|
|
73
|
-
|
|
75
|
+
logger.info("📋 Сводка конфигурации:")
|
|
76
|
+
|
|
74
77
|
summary = config.get_summary()
|
|
75
78
|
for key, value in summary.items():
|
|
76
79
|
logger.info(f" • {key}: {value}")
|
|
77
|
-
|
|
80
|
+
|
|
78
81
|
# Проверяем админские настройки
|
|
79
|
-
logger.info(
|
|
82
|
+
logger.info("\n👑 Админские настройки:")
|
|
80
83
|
logger.info(f" • Админов настроено: {len(config.ADMIN_TELEGRAM_IDS)}")
|
|
81
84
|
if config.ADMIN_TELEGRAM_IDS:
|
|
82
85
|
logger.info(f" • ID админов: {config.ADMIN_TELEGRAM_IDS}")
|
|
83
86
|
logger.info(f" • Таймаут сессий: {config.ADMIN_SESSION_TIMEOUT_MINUTES} мин")
|
|
84
|
-
logger.info(
|
|
85
|
-
|
|
87
|
+
logger.info(
|
|
88
|
+
f" • Режим отладки: {'Включен' if config.DEBUG_MODE else 'Выключен'}"
|
|
89
|
+
)
|
|
90
|
+
|
|
86
91
|
return config
|
|
87
92
|
except Exception as e:
|
|
88
93
|
logger.error(f"❌ Ошибка конфигурации: {e}")
|
|
89
94
|
return None
|
|
90
95
|
|
|
96
|
+
|
|
91
97
|
async def check_supabase(config: Config) -> bool:
|
|
92
98
|
"""Проверяем подключение к Supabase и новые таблицы"""
|
|
93
99
|
try:
|
|
94
100
|
client = SupabaseClient(config.SUPABASE_URL, config.SUPABASE_KEY)
|
|
95
101
|
await client.initialize()
|
|
96
|
-
|
|
97
|
-
# Пробуем выполнить простой запрос к основной
|
|
98
|
-
|
|
102
|
+
|
|
103
|
+
# Пробуем выполнить простой запрос к основной таблицеы
|
|
104
|
+
client.client.table("sales_users").select("id").limit(1).execute()
|
|
99
105
|
logger.info("✅ Supabase подключение успешно")
|
|
100
|
-
|
|
106
|
+
|
|
101
107
|
# Проверяем новые таблицы админской системы
|
|
102
|
-
admin_tables = [
|
|
103
|
-
|
|
104
|
-
'admin_user_conversations',
|
|
105
|
-
'session_events'
|
|
106
|
-
]
|
|
107
|
-
|
|
108
|
+
admin_tables = ["sales_admins", "admin_user_conversations", "session_events"]
|
|
109
|
+
|
|
108
110
|
logger.info("🔍 Проверка админских таблиц:")
|
|
109
111
|
for table in admin_tables:
|
|
110
112
|
try:
|
|
111
|
-
|
|
113
|
+
client.client.table(table).select("*").limit(1).execute()
|
|
112
114
|
logger.info(f" ✅ {table}")
|
|
113
115
|
except Exception as e:
|
|
114
116
|
logger.error(f" ❌ {table}: {e}")
|
|
115
|
-
|
|
117
|
+
|
|
116
118
|
# Проверяем новые колонки
|
|
117
119
|
logger.info("🔍 Проверка новых колонок:")
|
|
118
120
|
try:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
(
|
|
122
|
+
client.client.table("sales_chat_sessions")
|
|
123
|
+
.select("current_stage", "lead_quality_score")
|
|
124
|
+
.limit(1)
|
|
125
|
+
.execute()
|
|
126
|
+
)
|
|
122
127
|
logger.info(" ✅ sales_chat_sessions: current_stage, lead_quality_score")
|
|
123
128
|
except Exception as e:
|
|
124
129
|
logger.error(f" ❌ sales_chat_sessions новые колонки: {e}")
|
|
125
|
-
|
|
130
|
+
|
|
126
131
|
try:
|
|
127
|
-
|
|
132
|
+
(
|
|
133
|
+
client.client.table("sales_messages")
|
|
134
|
+
.select("ai_metadata")
|
|
135
|
+
.limit(1)
|
|
136
|
+
.execute()
|
|
137
|
+
)
|
|
128
138
|
logger.info(" ✅ sales_messages: ai_metadata")
|
|
129
139
|
except Exception as e:
|
|
130
140
|
logger.error(f" ❌ sales_messages.ai_metadata: {e}")
|
|
131
|
-
|
|
141
|
+
|
|
132
142
|
return True
|
|
133
143
|
except Exception as e:
|
|
134
144
|
logger.error(f"❌ Ошибка Supabase: {e}")
|
|
135
145
|
return False
|
|
136
146
|
|
|
147
|
+
|
|
137
148
|
async def check_openai(config: Config) -> bool:
|
|
138
149
|
"""Проверяем OpenAI API"""
|
|
139
150
|
try:
|
|
@@ -141,14 +152,14 @@ async def check_openai(config: Config) -> bool:
|
|
|
141
152
|
config.OPENAI_API_KEY,
|
|
142
153
|
config.OPENAI_MODEL,
|
|
143
154
|
config.OPENAI_MAX_TOKENS,
|
|
144
|
-
config.OPENAI_TEMPERATURE
|
|
155
|
+
config.OPENAI_TEMPERATURE,
|
|
145
156
|
)
|
|
146
|
-
|
|
157
|
+
|
|
147
158
|
health = await client.check_api_health()
|
|
148
|
-
|
|
159
|
+
|
|
149
160
|
if health:
|
|
150
161
|
logger.info("✅ OpenAI API доступен")
|
|
151
|
-
|
|
162
|
+
|
|
152
163
|
# Получаем список доступных моделей
|
|
153
164
|
models = await client.get_available_models()
|
|
154
165
|
if config.OPENAI_MODEL in models:
|
|
@@ -156,102 +167,110 @@ async def check_openai(config: Config) -> bool:
|
|
|
156
167
|
else:
|
|
157
168
|
logger.warning(f"⚠️ Модель {config.OPENAI_MODEL} не найдена в доступных")
|
|
158
169
|
logger.info(f" Доступные модели: {models[:5]}...")
|
|
159
|
-
|
|
170
|
+
|
|
160
171
|
return health
|
|
161
172
|
except Exception as e:
|
|
162
173
|
logger.error(f"❌ Ошибка OpenAI: {e}")
|
|
163
174
|
return False
|
|
164
175
|
|
|
176
|
+
|
|
165
177
|
async def check_prompts(config: Config) -> bool:
|
|
166
178
|
"""Проверяем промпты с новыми JSON инструкциями"""
|
|
167
179
|
try:
|
|
168
180
|
loader = PromptLoader(
|
|
169
|
-
prompts_dir=config.PROMT_FILES_DIR,
|
|
170
|
-
prompt_files=config.PROMPT_FILES
|
|
181
|
+
prompts_dir=config.PROMT_FILES_DIR, prompt_files=config.PROMPT_FILES
|
|
171
182
|
)
|
|
172
|
-
|
|
183
|
+
|
|
173
184
|
# Проверяем доступность файлов
|
|
174
185
|
validation = await loader.validate_prompts()
|
|
175
|
-
|
|
176
|
-
logger.info(
|
|
186
|
+
|
|
187
|
+
logger.info("📝 Статус промптов:")
|
|
177
188
|
for filename, status in validation.items():
|
|
178
189
|
status_icon = "✅" if status else "❌"
|
|
179
190
|
logger.info(f" {status_icon} {filename}")
|
|
180
|
-
|
|
191
|
+
|
|
181
192
|
# Пробуем загрузить системный промпт
|
|
182
193
|
if any(validation.values()):
|
|
183
194
|
system_prompt = await loader.load_system_prompt()
|
|
184
195
|
logger.info(f"✅ Системный промпт загружен ({len(system_prompt)} символов)")
|
|
185
|
-
|
|
196
|
+
|
|
186
197
|
# Проверяем наличие JSON инструкций
|
|
187
198
|
if "JSON МЕТАДАННЫМ" in system_prompt:
|
|
188
199
|
logger.info("✅ JSON инструкции включены в системный промпт")
|
|
189
200
|
else:
|
|
190
201
|
logger.warning("⚠️ JSON инструкции не найдены в системном промпте")
|
|
191
|
-
|
|
202
|
+
|
|
192
203
|
if '"этап":' in system_prompt:
|
|
193
204
|
logger.info("✅ Примеры JSON найдены в промпте")
|
|
194
205
|
else:
|
|
195
206
|
logger.warning("⚠️ Примеры JSON не найдены в промпте")
|
|
196
|
-
|
|
207
|
+
|
|
197
208
|
# Проверяем приветственное сообщение
|
|
198
209
|
welcome_message = await loader.load_welcome_message()
|
|
199
|
-
logger.info(
|
|
200
|
-
|
|
210
|
+
logger.info(
|
|
211
|
+
f"✅ Приветственное сообщение загружено ({len(welcome_message)} символов)"
|
|
212
|
+
)
|
|
213
|
+
|
|
201
214
|
# Проверяем справочное сообщение
|
|
202
215
|
help_message = await loader.load_help_message()
|
|
203
|
-
logger.info(
|
|
204
|
-
|
|
216
|
+
logger.info(
|
|
217
|
+
f"✅ Справочное сообщение загружено ({len(help_message)} символов)"
|
|
218
|
+
)
|
|
219
|
+
|
|
205
220
|
return True
|
|
206
221
|
else:
|
|
207
222
|
logger.error("❌ Не удалось загрузить ни одного промпта")
|
|
208
223
|
return False
|
|
209
|
-
|
|
224
|
+
|
|
210
225
|
except Exception as e:
|
|
211
226
|
logger.error(f"❌ Ошибка загрузки промптов: {e}")
|
|
212
227
|
return False
|
|
213
228
|
|
|
229
|
+
|
|
214
230
|
async def check_admin_system(config: Config) -> bool:
|
|
215
231
|
"""Проверяем админскую систему"""
|
|
216
232
|
try:
|
|
217
233
|
logger.info("👑 Проверка админской системы...")
|
|
218
|
-
|
|
234
|
+
|
|
219
235
|
if not config.ADMIN_TELEGRAM_IDS:
|
|
220
236
|
logger.warning("⚠️ Админы не настроены (ADMIN_TELEGRAM_IDS пуст)")
|
|
221
237
|
return False
|
|
222
|
-
|
|
238
|
+
|
|
223
239
|
# Проверяем AdminManager
|
|
224
240
|
supabase_client = SupabaseClient(config.SUPABASE_URL, config.SUPABASE_KEY)
|
|
225
241
|
await supabase_client.initialize()
|
|
226
|
-
|
|
242
|
+
|
|
227
243
|
admin_manager = AdminManager(config, supabase_client)
|
|
228
|
-
logger.info(
|
|
229
|
-
|
|
244
|
+
logger.info(
|
|
245
|
+
f"✅ AdminManager инициализирован ({len(admin_manager.admin_ids)} админов)"
|
|
246
|
+
)
|
|
247
|
+
|
|
230
248
|
# Проверяем ConversationManager
|
|
231
|
-
|
|
249
|
+
ConversationManager(supabase_client, admin_manager)
|
|
232
250
|
logger.info("✅ ConversationManager инициализирован")
|
|
233
|
-
|
|
251
|
+
|
|
234
252
|
# Проверяем AnalyticsManager
|
|
235
253
|
analytics_manager = AnalyticsManager(supabase_client)
|
|
236
|
-
|
|
254
|
+
|
|
237
255
|
# Тестируем получение статистики
|
|
238
|
-
|
|
256
|
+
await analytics_manager.get_funnel_stats(1)
|
|
239
257
|
logger.info("✅ AnalyticsManager работает")
|
|
240
|
-
|
|
258
|
+
|
|
241
259
|
logger.info("✅ Админская система готова к работе")
|
|
242
260
|
return True
|
|
243
|
-
|
|
261
|
+
|
|
244
262
|
except Exception as e:
|
|
245
263
|
logger.error(f"❌ Ошибка админской системы: {e}")
|
|
246
264
|
return False
|
|
247
265
|
|
|
266
|
+
|
|
248
267
|
async def check_json_parsing() -> bool:
|
|
249
268
|
"""Проверяем парсинг JSON метаданных"""
|
|
250
269
|
try:
|
|
251
270
|
logger.info("🧪 Проверка парсинга JSON...")
|
|
252
|
-
|
|
271
|
+
|
|
253
272
|
# Тестовые случаи
|
|
254
|
-
test_response =
|
|
273
|
+
test_response = """Отлично! Записал ваш номер телефона.
|
|
255
274
|
|
|
256
275
|
{
|
|
257
276
|
"этап": "contacts",
|
|
@@ -262,10 +281,10 @@ async def check_json_parsing() -> bool:
|
|
|
262
281
|
"инфо": "Иван Петров +79219603144"
|
|
263
282
|
}
|
|
264
283
|
]
|
|
265
|
-
}
|
|
266
|
-
|
|
284
|
+
}"""
|
|
285
|
+
|
|
267
286
|
response_text, metadata = parse_ai_response(test_response)
|
|
268
|
-
|
|
287
|
+
|
|
269
288
|
if metadata:
|
|
270
289
|
logger.info("✅ JSON успешно распарсен")
|
|
271
290
|
logger.info(f" Этап: {metadata.get('этап')}")
|
|
@@ -275,57 +294,64 @@ async def check_json_parsing() -> bool:
|
|
|
275
294
|
else:
|
|
276
295
|
logger.error("❌ Не удалось распарсить JSON")
|
|
277
296
|
return False
|
|
278
|
-
|
|
297
|
+
|
|
279
298
|
except Exception as e:
|
|
280
299
|
logger.error(f"❌ Ошибка парсинга JSON: {e}")
|
|
281
300
|
return False
|
|
282
301
|
|
|
302
|
+
|
|
283
303
|
async def check_database_structure() -> bool:
|
|
284
304
|
"""Проверяем структуру базы данных"""
|
|
285
305
|
try:
|
|
286
306
|
logger.info("📊 Проверка структуры БД...")
|
|
287
|
-
|
|
307
|
+
|
|
288
308
|
# Проверяем наличие SQL файлов
|
|
289
309
|
root_dir = Path(os.getcwd())
|
|
290
310
|
sql_files = [
|
|
291
|
-
(
|
|
292
|
-
|
|
311
|
+
(
|
|
312
|
+
"database_structure.sql",
|
|
313
|
+
"smart_bot_factory/database/database_structure.sql",
|
|
314
|
+
),
|
|
315
|
+
("admin_migration.sql", "smart_bot_factory/admin/admin_migration.sql"),
|
|
293
316
|
]
|
|
294
|
-
|
|
317
|
+
|
|
295
318
|
for sql_name, sql_path in sql_files:
|
|
296
319
|
full_path = root_dir / sql_path
|
|
297
320
|
if full_path.exists():
|
|
298
321
|
logger.info(f"✅ {sql_name} найден: {sql_path}")
|
|
299
322
|
else:
|
|
300
323
|
logger.error(f"❌ {sql_name} не найден: {sql_path}")
|
|
301
|
-
|
|
324
|
+
|
|
302
325
|
logger.info("ℹ️ Для проверки таблиц в БД запустите SQL скрипты в Supabase")
|
|
303
326
|
return True
|
|
304
|
-
|
|
327
|
+
|
|
305
328
|
except Exception as e:
|
|
306
329
|
logger.error(f"❌ Ошибка проверки БД: {e}")
|
|
307
330
|
return False
|
|
308
331
|
|
|
332
|
+
|
|
309
333
|
async def check_environment() -> None:
|
|
310
334
|
"""Проверяем окружение"""
|
|
311
335
|
logger.info("🔧 Проверка окружения...")
|
|
312
|
-
|
|
336
|
+
|
|
313
337
|
# Проверяем Python зависимости
|
|
314
338
|
dependencies = [
|
|
315
|
-
(
|
|
316
|
-
(
|
|
317
|
-
(
|
|
318
|
-
(
|
|
319
|
-
(
|
|
339
|
+
("aiogram", "aiogram"),
|
|
340
|
+
("supabase", "supabase"),
|
|
341
|
+
("openai", "openai"),
|
|
342
|
+
("python-dotenv", "dotenv"),
|
|
343
|
+
("aiofiles", "aiofiles"),
|
|
320
344
|
]
|
|
321
|
-
|
|
345
|
+
|
|
322
346
|
for dep_name, import_name in dependencies:
|
|
323
347
|
try:
|
|
324
|
-
if import_name ==
|
|
348
|
+
if import_name == "aiogram":
|
|
325
349
|
import aiogram
|
|
350
|
+
|
|
326
351
|
logger.info(f"✅ {dep_name} {aiogram.__version__}")
|
|
327
|
-
elif import_name ==
|
|
352
|
+
elif import_name == "openai":
|
|
328
353
|
import openai
|
|
354
|
+
|
|
329
355
|
logger.info(f"✅ {dep_name} {openai.version.VERSION}")
|
|
330
356
|
else:
|
|
331
357
|
__import__(import_name)
|
|
@@ -333,56 +359,58 @@ async def check_environment() -> None:
|
|
|
333
359
|
except ImportError:
|
|
334
360
|
logger.error(f"❌ {dep_name} не установлен")
|
|
335
361
|
|
|
362
|
+
|
|
336
363
|
async def run_quick_test() -> bool:
|
|
337
364
|
"""Быстрый тест основного функционала"""
|
|
338
365
|
try:
|
|
339
366
|
logger.info("⚡ Быстрый тест компонентов...")
|
|
340
|
-
|
|
367
|
+
|
|
341
368
|
config = Config()
|
|
342
|
-
|
|
369
|
+
|
|
343
370
|
if config.ADMIN_TELEGRAM_IDS:
|
|
344
371
|
logger.info(f"✅ {len(config.ADMIN_TELEGRAM_IDS)} админов настроено")
|
|
345
372
|
else:
|
|
346
373
|
logger.warning("⚠️ Админы не настроены")
|
|
347
|
-
|
|
374
|
+
|
|
348
375
|
# Тест парсинга JSON
|
|
349
376
|
await check_json_parsing()
|
|
350
|
-
|
|
377
|
+
|
|
351
378
|
return True
|
|
352
|
-
|
|
379
|
+
|
|
353
380
|
except Exception as e:
|
|
354
381
|
logger.error(f"❌ Ошибка быстрого теста: {e}")
|
|
355
382
|
return False
|
|
356
383
|
|
|
384
|
+
|
|
357
385
|
async def check_setup(bot_name: str = "growthmed-october-24") -> bool:
|
|
358
386
|
"""
|
|
359
387
|
Проверяет настройку бота
|
|
360
|
-
|
|
388
|
+
|
|
361
389
|
Args:
|
|
362
390
|
bot_name: Имя бота для проверки
|
|
363
|
-
|
|
391
|
+
|
|
364
392
|
Returns:
|
|
365
393
|
bool: True если все критические проверки пройдены, False если есть критические ошибки
|
|
366
394
|
"""
|
|
367
395
|
logger.info(f"🚀 Проверка настройки Telegram Sales Bot v2.0: {bot_name}")
|
|
368
396
|
logger.info(f"🤖 Bot ID будет автоопределен как: {bot_name}\n")
|
|
369
|
-
|
|
397
|
+
|
|
370
398
|
# Настраиваем окружение для бота (автоматически устанавливает BOT_ID)
|
|
371
399
|
config_dir = setup_bot_environment(bot_name)
|
|
372
400
|
if not config_dir:
|
|
373
401
|
return False
|
|
374
|
-
|
|
402
|
+
|
|
375
403
|
# Проверяем окружение
|
|
376
404
|
await check_environment()
|
|
377
405
|
logger.info("")
|
|
378
|
-
|
|
406
|
+
|
|
379
407
|
# Проверяем конфигурацию
|
|
380
408
|
config = await check_config()
|
|
381
409
|
if not config:
|
|
382
410
|
logger.error("\n❌ Невозможно продолжить без правильной конфигурации")
|
|
383
411
|
return False
|
|
384
412
|
logger.info("")
|
|
385
|
-
|
|
413
|
+
|
|
386
414
|
# Основные проверки
|
|
387
415
|
checks: List[Tuple[str, bool]] = []
|
|
388
416
|
for name, check_coro in [
|
|
@@ -392,22 +420,22 @@ async def check_setup(bot_name: str = "growthmed-october-24") -> bool:
|
|
|
392
420
|
("Промпты", check_prompts(config)),
|
|
393
421
|
("Админская система", check_admin_system(config)),
|
|
394
422
|
("JSON парсинг", check_json_parsing()),
|
|
395
|
-
("Быстрый тест", run_quick_test())
|
|
423
|
+
("Быстрый тест", run_quick_test()),
|
|
396
424
|
]:
|
|
397
425
|
logger.info(f"\n🔍 Проверка: {name}")
|
|
398
426
|
result = await check_coro
|
|
399
427
|
checks.append((name, result))
|
|
400
|
-
|
|
428
|
+
|
|
401
429
|
# Итоговый результат
|
|
402
430
|
logger.info(f"\n{'='*60}")
|
|
403
431
|
logger.info(f"📋 ИТОГОВЫЙ ОТЧЕТ для {bot_name}:")
|
|
404
|
-
|
|
432
|
+
|
|
405
433
|
all_passed = True
|
|
406
434
|
critical_failed = False
|
|
407
|
-
|
|
435
|
+
|
|
408
436
|
# Критические компоненты
|
|
409
437
|
critical_checks = ["Supabase", "OpenAI", "Промпты"]
|
|
410
|
-
|
|
438
|
+
|
|
411
439
|
for name, passed in checks:
|
|
412
440
|
if name in critical_checks:
|
|
413
441
|
status = "✅ ПРОЙДЕНА" if passed else "❌ КРИТИЧЕСКАЯ ОШИБКА"
|
|
@@ -415,14 +443,14 @@ async def check_setup(bot_name: str = "growthmed-october-24") -> bool:
|
|
|
415
443
|
critical_failed = True
|
|
416
444
|
else:
|
|
417
445
|
status = "✅ ПРОЙДЕНА" if passed else "⚠️ ПРЕДУПРЕЖДЕНИЕ"
|
|
418
|
-
|
|
446
|
+
|
|
419
447
|
logger.info(f" {name}: {status}")
|
|
420
448
|
if not passed:
|
|
421
449
|
all_passed = False
|
|
422
|
-
|
|
450
|
+
|
|
423
451
|
passed_count = sum(1 for _, passed in checks if passed)
|
|
424
452
|
logger.info(f"\n📊 Результат: {passed_count}/{len(checks)} проверок пройдено")
|
|
425
|
-
|
|
453
|
+
|
|
426
454
|
if critical_failed:
|
|
427
455
|
logger.error("\n🚨 КРИТИЧЕСКИЕ ОШИБКИ! Бот не может быть запущен.")
|
|
428
456
|
logger.error(" Исправьте критические ошибки перед запуском.")
|
|
@@ -430,37 +458,44 @@ async def check_setup(bot_name: str = "growthmed-october-24") -> bool:
|
|
|
430
458
|
logger.info("\n🎉 Все проверки пройдены! Бот готов к запуску.")
|
|
431
459
|
logger.info(f" Запустите: python {bot_name}.py")
|
|
432
460
|
if config.ADMIN_TELEGRAM_IDS:
|
|
433
|
-
logger.info(
|
|
461
|
+
logger.info(
|
|
462
|
+
f" 👑 Админский доступ настроен для: {config.ADMIN_TELEGRAM_IDS}"
|
|
463
|
+
)
|
|
434
464
|
else:
|
|
435
465
|
logger.warning("\n⚠️ Есть предупреждения, но бот может работать.")
|
|
436
|
-
logger.warning(
|
|
437
|
-
|
|
466
|
+
logger.warning(
|
|
467
|
+
" Рекомендуется исправить предупреждения для полного функционала."
|
|
468
|
+
)
|
|
469
|
+
|
|
438
470
|
if config and config.DEBUG_MODE:
|
|
439
|
-
logger.warning(
|
|
440
|
-
|
|
471
|
+
logger.warning(
|
|
472
|
+
"\n🐛 РЕЖИМ ОТЛАДКИ ВКЛЮЧЕН - JSON будет показываться пользователям"
|
|
473
|
+
)
|
|
474
|
+
|
|
441
475
|
logger.info(f"{'='*60}")
|
|
442
|
-
|
|
476
|
+
|
|
443
477
|
return not critical_failed
|
|
444
478
|
|
|
479
|
+
|
|
445
480
|
def main():
|
|
446
481
|
"""Точка входа для запуска из командной строки"""
|
|
447
482
|
# Настройка логирования
|
|
448
|
-
logging.basicConfig(level=logging.INFO, format=
|
|
449
|
-
|
|
483
|
+
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
|
484
|
+
|
|
450
485
|
logger.info("🔍 Утилита проверки настройки бота")
|
|
451
486
|
logger.info("Использование:")
|
|
452
487
|
logger.info(" python -m smart_bot_factory.setup_checker [bot_name]")
|
|
453
488
|
logger.info(" python -m smart_bot_factory.setup_checker growthmed-october-24")
|
|
454
489
|
logger.info("")
|
|
455
|
-
|
|
456
|
-
if len(sys.argv) > 1 and sys.argv[1] in [
|
|
490
|
+
|
|
491
|
+
if len(sys.argv) > 1 and sys.argv[1] in ["-h", "--help", "help"]:
|
|
457
492
|
return
|
|
458
|
-
|
|
493
|
+
|
|
459
494
|
# Определяем какого бота проверять
|
|
460
495
|
bot_name = "growthmed-october-24" # по умолчанию
|
|
461
496
|
if len(sys.argv) > 1:
|
|
462
497
|
bot_name = sys.argv[1]
|
|
463
|
-
|
|
498
|
+
|
|
464
499
|
try:
|
|
465
500
|
success = asyncio.run(check_setup(bot_name))
|
|
466
501
|
if not success:
|
|
@@ -472,5 +507,6 @@ def main():
|
|
|
472
507
|
logger.exception("Стек ошибки:")
|
|
473
508
|
sys.exit(1)
|
|
474
509
|
|
|
510
|
+
|
|
475
511
|
if __name__ == "__main__":
|
|
476
512
|
main()
|