smart-bot-factory 0.3.8__py3-none-any.whl → 0.3.10__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/admin_manager.py +2 -2
- smart_bot_factory/core/bot_utils.py +54 -24
- smart_bot_factory/core/conversation_manager.py +36 -13
- smart_bot_factory/core/decorators.py +125 -39
- smart_bot_factory/core/message_sender.py +3 -2
- smart_bot_factory/core/router.py +9 -0
- smart_bot_factory/handlers/handlers.py +19 -24
- smart_bot_factory/integrations/supabase_client.py +60 -17
- {smart_bot_factory-0.3.8.dist-info → smart_bot_factory-0.3.10.dist-info}/METADATA +1 -1
- {smart_bot_factory-0.3.8.dist-info → smart_bot_factory-0.3.10.dist-info}/RECORD +13 -13
- {smart_bot_factory-0.3.8.dist-info → smart_bot_factory-0.3.10.dist-info}/WHEEL +0 -0
- {smart_bot_factory-0.3.8.dist-info → smart_bot_factory-0.3.10.dist-info}/entry_points.txt +0 -0
- {smart_bot_factory-0.3.8.dist-info → smart_bot_factory-0.3.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -122,8 +122,8 @@ class AdminManager:
|
|
|
122
122
|
|
|
123
123
|
async def notify_admins(self, message: str, exclude_admin: int = None):
|
|
124
124
|
"""Отправляет уведомление всем активным админам"""
|
|
125
|
-
from
|
|
126
|
-
|
|
125
|
+
from ..handlers.handlers import get_global_var
|
|
126
|
+
bot = get_global_var("bot")
|
|
127
127
|
|
|
128
128
|
active_admins = await self.get_active_admins()
|
|
129
129
|
|
|
@@ -245,25 +245,33 @@ async def process_events(session_id: str, events: list, user_id: int) -> bool:
|
|
|
245
245
|
f"🔍 Старые scheduled_tasks: {list(scheduled_tasks.keys())}"
|
|
246
246
|
)
|
|
247
247
|
|
|
248
|
-
# Сначала пробуем как обычное событие
|
|
248
|
+
# Сначала пробуем как обычное событие или scheduled task
|
|
249
|
+
handler_info = None
|
|
250
|
+
handler_type = None
|
|
251
|
+
|
|
249
252
|
if event_type in event_handlers:
|
|
253
|
+
handler_info = event_handlers.get(event_type, {})
|
|
254
|
+
handler_type = "event"
|
|
255
|
+
elif event_type in scheduled_tasks:
|
|
256
|
+
handler_info = scheduled_tasks.get(event_type, {})
|
|
257
|
+
handler_type = "task"
|
|
258
|
+
|
|
259
|
+
if handler_info:
|
|
250
260
|
from ..core.decorators import execute_event_handler
|
|
251
261
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
"send_ai_response", True
|
|
256
|
-
)
|
|
262
|
+
once_only = handler_info.get("once_only", True)
|
|
263
|
+
send_ai_response_flag = handler_info.get("send_ai_response", True)
|
|
264
|
+
should_notify = handler_info.get("notify", False) # Получаем notify из handler_info
|
|
257
265
|
|
|
258
266
|
logger.info(
|
|
259
|
-
f" 🔍
|
|
267
|
+
f" 🔍 {handler_type.title()} '{event_type}': once_only={once_only}, send_ai_response={send_ai_response_flag}, notify={should_notify}"
|
|
260
268
|
)
|
|
261
269
|
|
|
262
270
|
# Проверяем флаг send_ai_response ИЗ ДЕКОРАТОРА
|
|
263
271
|
if not send_ai_response_flag:
|
|
264
272
|
should_send_ai_response = False
|
|
265
273
|
logger.warning(
|
|
266
|
-
f" 🔇🔇🔇
|
|
274
|
+
f" 🔇🔇🔇 {handler_type.upper()} '{event_type}' ЗАПРЕТИЛ ОТПРАВКУ СООБЩЕНИЯ ОТ ИИ (send_ai_response=False) 🔇🔇🔇"
|
|
267
275
|
)
|
|
268
276
|
|
|
269
277
|
# Если once_only=True - проверяем в БД наличие выполненных событий
|
|
@@ -301,14 +309,21 @@ async def process_events(session_id: str, events: list, user_id: int) -> bool:
|
|
|
301
309
|
|
|
302
310
|
# Немедленно выполняем событие
|
|
303
311
|
logger.info(
|
|
304
|
-
f" 🎯 Немедленно выполняем
|
|
312
|
+
f" 🎯 Немедленно выполняем {handler_type}: '{event_type}'"
|
|
305
313
|
)
|
|
306
314
|
|
|
307
315
|
try:
|
|
308
|
-
# Выполняем
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
316
|
+
# Выполняем обработчик в зависимости от типа
|
|
317
|
+
if handler_type == "event":
|
|
318
|
+
result = await execute_event_handler(
|
|
319
|
+
event_type, user_id, event_info
|
|
320
|
+
)
|
|
321
|
+
elif handler_type == "task":
|
|
322
|
+
result = await execute_scheduled_task_from_event(
|
|
323
|
+
user_id, event_type, event_info, session_id
|
|
324
|
+
)
|
|
325
|
+
else:
|
|
326
|
+
raise ValueError(f"Неизвестный тип обработчика: {handler_type}")
|
|
312
327
|
|
|
313
328
|
# Проверяем наличие поля 'info' для дашборда
|
|
314
329
|
import json
|
|
@@ -353,14 +368,14 @@ async def process_events(session_id: str, events: list, user_id: int) -> bool:
|
|
|
353
368
|
)
|
|
354
369
|
event_id = response.data[0]["id"]
|
|
355
370
|
|
|
356
|
-
should_notify
|
|
357
|
-
|
|
371
|
+
# should_notify уже получен из handler_info выше
|
|
358
372
|
logger.info(
|
|
359
373
|
f" ✅ Событие {event_id} выполнено и сохранено как completed"
|
|
360
374
|
)
|
|
361
375
|
|
|
362
376
|
except Exception as e:
|
|
363
377
|
logger.error(f" ❌ Ошибка выполнения события: {e}")
|
|
378
|
+
|
|
364
379
|
# Сохраняем ошибку в БД
|
|
365
380
|
event_record = {
|
|
366
381
|
"event_type": event_type,
|
|
@@ -377,10 +392,15 @@ async def process_events(session_id: str, events: list, user_id: int) -> bool:
|
|
|
377
392
|
if supabase_client.bot_id:
|
|
378
393
|
event_record["bot_id"] = supabase_client.bot_id
|
|
379
394
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
395
|
+
try:
|
|
396
|
+
supabase_client.client.table("scheduled_events").insert(
|
|
397
|
+
event_record
|
|
398
|
+
).execute()
|
|
399
|
+
logger.info(f" 💾 Ошибка сохранена в БД")
|
|
400
|
+
except Exception as db_error:
|
|
401
|
+
logger.error(f" ❌ Не удалось сохранить ошибку в БД: {db_error}")
|
|
402
|
+
|
|
403
|
+
continue # Переходим к следующему событию после сохранения ошибки
|
|
384
404
|
|
|
385
405
|
# Если не user_event, пробуем как запланированную задачу
|
|
386
406
|
elif event_type in scheduled_tasks:
|
|
@@ -469,12 +489,22 @@ async def process_events(session_id: str, events: list, user_id: int) -> bool:
|
|
|
469
489
|
logger.error(f" ❌ Ошибка в обработчике/задаче: {e}")
|
|
470
490
|
logger.exception(" Стек ошибки:")
|
|
471
491
|
|
|
472
|
-
#
|
|
473
|
-
if
|
|
474
|
-
|
|
475
|
-
|
|
492
|
+
# Проверяем notify_time для scheduled_task
|
|
493
|
+
if handler_type == "task":
|
|
494
|
+
notify_time = handler_info.get("notify_time", "after")
|
|
495
|
+
# Для 'before' уведомляем сразу при создании
|
|
496
|
+
if notify_time == "before" and should_notify:
|
|
497
|
+
await notify_admins_about_event(user_id, event)
|
|
498
|
+
logger.info(" ✅ Админы уведомлены (notify_time=before)")
|
|
499
|
+
elif notify_time == "after":
|
|
500
|
+
logger.info(" ⏳ Уведомление будет отправлено после выполнения задачи (notify_time=after)")
|
|
476
501
|
else:
|
|
477
|
-
|
|
502
|
+
# Для обычных событий уведомляем сразу
|
|
503
|
+
if should_notify:
|
|
504
|
+
await notify_admins_about_event(user_id, event)
|
|
505
|
+
logger.info(" ✅ Админы уведомлены")
|
|
506
|
+
else:
|
|
507
|
+
logger.info(f" 🔕 Уведомления админам отключены для '{event_type}'")
|
|
478
508
|
|
|
479
509
|
except Exception as e:
|
|
480
510
|
logger.error(f"❌ Ошибка обработки события {event}: {e}")
|
|
@@ -72,15 +72,20 @@ class ConversationManager:
|
|
|
72
72
|
|
|
73
73
|
try:
|
|
74
74
|
# Получаем последние 5 сообщений (сортируем по убыванию и берем первые 5)
|
|
75
|
-
|
|
75
|
+
query = (
|
|
76
76
|
self.supabase.client.table("sales_messages")
|
|
77
77
|
.select("role", "content", "created_at")
|
|
78
78
|
.eq("session_id", session_id)
|
|
79
79
|
.order("created_at", desc=True)
|
|
80
80
|
.limit(5)
|
|
81
|
-
.execute()
|
|
82
81
|
)
|
|
83
82
|
|
|
83
|
+
# Добавляем фильтр по bot_id если он указан
|
|
84
|
+
if self.supabase.bot_id:
|
|
85
|
+
query = query.eq("bot_id", self.supabase.bot_id)
|
|
86
|
+
|
|
87
|
+
response = query.execute()
|
|
88
|
+
|
|
84
89
|
recent_messages = response.data if response.data else []
|
|
85
90
|
|
|
86
91
|
if not recent_messages:
|
|
@@ -122,12 +127,17 @@ class ConversationManager:
|
|
|
122
127
|
async def get_user_display_name(self, user_id: int) -> str:
|
|
123
128
|
"""Получает красивое отображение пользователя с username"""
|
|
124
129
|
try:
|
|
125
|
-
|
|
130
|
+
query = (
|
|
126
131
|
self.supabase.client.table("sales_users")
|
|
127
132
|
.select("first_name", "last_name", "username")
|
|
128
133
|
.eq("telegram_id", user_id)
|
|
129
|
-
.execute()
|
|
130
134
|
)
|
|
135
|
+
|
|
136
|
+
# Добавляем фильтр по bot_id если он указан
|
|
137
|
+
if self.supabase.bot_id:
|
|
138
|
+
query = query.eq("bot_id", self.supabase.bot_id)
|
|
139
|
+
|
|
140
|
+
response = query.execute()
|
|
131
141
|
|
|
132
142
|
if response.data:
|
|
133
143
|
user_info = response.data[0]
|
|
@@ -316,8 +326,7 @@ class ConversationManager:
|
|
|
316
326
|
|
|
317
327
|
try:
|
|
318
328
|
# Отправляем сообщение как от бота
|
|
319
|
-
|
|
320
|
-
await send_message_by_human(user_id, message.text, parse_mode=parse_mode)
|
|
329
|
+
await send_message_by_human(user_id, message.text)
|
|
321
330
|
|
|
322
331
|
# Сохраняем в БД как сообщение ассистента
|
|
323
332
|
session_info = await supabase_client.get_active_session(user_id)
|
|
@@ -406,27 +415,36 @@ class ConversationManager:
|
|
|
406
415
|
logger.info("🔍 Ищем активные диалоги админов...")
|
|
407
416
|
|
|
408
417
|
# Получаем все активные диалоги
|
|
409
|
-
|
|
418
|
+
query = (
|
|
410
419
|
self.supabase.client.table("admin_user_conversations")
|
|
411
420
|
.select("id", "admin_id", "user_id", "started_at", "auto_end_at")
|
|
412
421
|
.eq("status", "active")
|
|
413
|
-
.order("started_at", desc=True)
|
|
414
|
-
.execute()
|
|
415
422
|
)
|
|
416
423
|
|
|
424
|
+
# Добавляем фильтр по bot_id если он указан
|
|
425
|
+
if self.supabase.bot_id:
|
|
426
|
+
query = query.eq("bot_id", self.supabase.bot_id)
|
|
427
|
+
|
|
428
|
+
response = query.order("started_at", desc=True).execute()
|
|
429
|
+
|
|
417
430
|
logger.info(f"📊 Найдено {len(response.data)} активных диалогов в БД")
|
|
418
431
|
|
|
419
432
|
conversations = []
|
|
420
433
|
for conv in response.data:
|
|
421
434
|
# Получаем информацию о пользователе
|
|
422
435
|
try:
|
|
423
|
-
|
|
436
|
+
user_query = (
|
|
424
437
|
self.supabase.client.table("sales_users")
|
|
425
438
|
.select("first_name", "last_name", "username")
|
|
426
439
|
.eq("telegram_id", conv["user_id"])
|
|
427
|
-
.execute()
|
|
428
440
|
)
|
|
429
441
|
|
|
442
|
+
# Добавляем фильтр по bot_id если он указан
|
|
443
|
+
if self.supabase.bot_id:
|
|
444
|
+
user_query = user_query.eq("bot_id", self.supabase.bot_id)
|
|
445
|
+
|
|
446
|
+
user_response = user_query.execute()
|
|
447
|
+
|
|
430
448
|
user_info = user_response.data[0] if user_response.data else {}
|
|
431
449
|
except Exception as e:
|
|
432
450
|
logger.error(
|
|
@@ -436,13 +454,18 @@ class ConversationManager:
|
|
|
436
454
|
|
|
437
455
|
# Получаем информацию об админе
|
|
438
456
|
try:
|
|
439
|
-
|
|
457
|
+
admin_query = (
|
|
440
458
|
self.supabase.client.table("sales_admins")
|
|
441
459
|
.select("first_name", "last_name", "username")
|
|
442
460
|
.eq("telegram_id", conv["admin_id"])
|
|
443
|
-
.execute()
|
|
444
461
|
)
|
|
445
462
|
|
|
463
|
+
# Добавляем фильтр по bot_id если он указан
|
|
464
|
+
if self.supabase.bot_id:
|
|
465
|
+
admin_query = admin_query.eq("bot_id", self.supabase.bot_id)
|
|
466
|
+
|
|
467
|
+
admin_response = admin_query.execute()
|
|
468
|
+
|
|
446
469
|
admin_info = admin_response.data[0] if admin_response.data else {}
|
|
447
470
|
except Exception as e:
|
|
448
471
|
logger.error(
|
|
@@ -476,6 +476,7 @@ def event_handler(
|
|
|
476
476
|
def schedule_task(
|
|
477
477
|
task_name: str,
|
|
478
478
|
notify: bool = False,
|
|
479
|
+
notify_time: str = "after", # 'after' или 'before'
|
|
479
480
|
smart_check: bool = True,
|
|
480
481
|
once_only: bool = True,
|
|
481
482
|
delay: Union[str, int] = None,
|
|
@@ -1310,6 +1311,11 @@ async def save_immediate_event(
|
|
|
1310
1311
|
f"Событие '{event_type}' уже обрабатывалось (once_only=True)"
|
|
1311
1312
|
)
|
|
1312
1313
|
|
|
1314
|
+
# Получаем bot_id
|
|
1315
|
+
bot_id = supabase_client.bot_id
|
|
1316
|
+
if not bot_id:
|
|
1317
|
+
logger.warning("⚠️ bot_id не указан при создании immediate_event")
|
|
1318
|
+
|
|
1313
1319
|
event_record = {
|
|
1314
1320
|
"event_type": event_type,
|
|
1315
1321
|
"event_category": "user_event",
|
|
@@ -1318,12 +1324,9 @@ async def save_immediate_event(
|
|
|
1318
1324
|
"scheduled_at": None, # Немедленное выполнение
|
|
1319
1325
|
"status": "immediate",
|
|
1320
1326
|
"session_id": session_id,
|
|
1327
|
+
"bot_id": bot_id, # Всегда добавляем bot_id
|
|
1321
1328
|
}
|
|
1322
1329
|
|
|
1323
|
-
# 🆕 Добавляем bot_id если указан
|
|
1324
|
-
if supabase_client.bot_id:
|
|
1325
|
-
event_record["bot_id"] = supabase_client.bot_id
|
|
1326
|
-
|
|
1327
1330
|
try:
|
|
1328
1331
|
response = (
|
|
1329
1332
|
supabase_client.client.table("scheduled_events")
|
|
@@ -1375,6 +1378,11 @@ async def save_scheduled_task(
|
|
|
1375
1378
|
|
|
1376
1379
|
scheduled_at = datetime.now(timezone.utc) + timedelta(seconds=delay_seconds)
|
|
1377
1380
|
|
|
1381
|
+
# Получаем bot_id
|
|
1382
|
+
bot_id = supabase_client.bot_id
|
|
1383
|
+
if not bot_id:
|
|
1384
|
+
logger.warning("⚠️ bot_id не указан при создании scheduled_task")
|
|
1385
|
+
|
|
1378
1386
|
event_record = {
|
|
1379
1387
|
"event_type": task_name,
|
|
1380
1388
|
"event_category": "scheduled_task",
|
|
@@ -1383,12 +1391,9 @@ async def save_scheduled_task(
|
|
|
1383
1391
|
"scheduled_at": scheduled_at.isoformat(),
|
|
1384
1392
|
"status": "pending",
|
|
1385
1393
|
"session_id": session_id,
|
|
1394
|
+
"bot_id": bot_id, # Всегда добавляем bot_id
|
|
1386
1395
|
}
|
|
1387
1396
|
|
|
1388
|
-
# 🆕 Добавляем bot_id если указан
|
|
1389
|
-
if supabase_client.bot_id:
|
|
1390
|
-
event_record["bot_id"] = supabase_client.bot_id
|
|
1391
|
-
|
|
1392
1397
|
try:
|
|
1393
1398
|
response = (
|
|
1394
1399
|
supabase_client.client.table("scheduled_events")
|
|
@@ -1445,6 +1450,11 @@ async def save_global_event(
|
|
|
1445
1450
|
scheduled_at = datetime.now(timezone.utc) + timedelta(seconds=delay_seconds)
|
|
1446
1451
|
status = "pending"
|
|
1447
1452
|
|
|
1453
|
+
# Получаем bot_id
|
|
1454
|
+
bot_id = supabase_client.bot_id
|
|
1455
|
+
if not bot_id:
|
|
1456
|
+
logger.warning("⚠️ bot_id не указан при создании global_event")
|
|
1457
|
+
|
|
1448
1458
|
event_record = {
|
|
1449
1459
|
"event_type": handler_type,
|
|
1450
1460
|
"event_category": "global_handler",
|
|
@@ -1452,12 +1462,9 @@ async def save_global_event(
|
|
|
1452
1462
|
"event_data": handler_data,
|
|
1453
1463
|
"scheduled_at": scheduled_at.isoformat() if scheduled_at else None,
|
|
1454
1464
|
"status": status,
|
|
1465
|
+
"bot_id": bot_id, # Всегда добавляем bot_id (глобальные события тоже привязаны к боту)
|
|
1455
1466
|
}
|
|
1456
1467
|
|
|
1457
|
-
# 🆕 Добавляем bot_id если указан (глобальные события тоже привязаны к боту)
|
|
1458
|
-
if supabase_client.bot_id:
|
|
1459
|
-
event_record["bot_id"] = supabase_client.bot_id
|
|
1460
|
-
|
|
1461
1468
|
try:
|
|
1462
1469
|
response = (
|
|
1463
1470
|
supabase_client.client.table("scheduled_events")
|
|
@@ -1503,22 +1510,32 @@ async def update_event_result(
|
|
|
1503
1510
|
update_data["last_error"] = error_message
|
|
1504
1511
|
# Получаем текущее количество попыток
|
|
1505
1512
|
try:
|
|
1506
|
-
|
|
1513
|
+
query = (
|
|
1507
1514
|
supabase_client.client.table("scheduled_events")
|
|
1508
1515
|
.select("retry_count")
|
|
1509
1516
|
.eq("id", event_id)
|
|
1510
|
-
.execute()
|
|
1511
|
-
.data[0]["retry_count"]
|
|
1512
1517
|
)
|
|
1518
|
+
|
|
1519
|
+
# Добавляем фильтр по bot_id если указан
|
|
1520
|
+
if supabase_client.bot_id:
|
|
1521
|
+
query = query.eq("bot_id", supabase_client.bot_id)
|
|
1522
|
+
|
|
1523
|
+
current_retry = query.execute().data[0]["retry_count"]
|
|
1513
1524
|
update_data["retry_count"] = current_retry + 1
|
|
1514
1525
|
except Exception:
|
|
1515
1526
|
logger.debug("Не удалось получить текущее количество попыток, устанавливаем 1")
|
|
1516
1527
|
update_data["retry_count"] = 1
|
|
1517
1528
|
|
|
1518
1529
|
try:
|
|
1519
|
-
supabase_client.client.table("scheduled_events").update(update_data).eq(
|
|
1530
|
+
query = supabase_client.client.table("scheduled_events").update(update_data).eq(
|
|
1520
1531
|
"id", event_id
|
|
1521
|
-
)
|
|
1532
|
+
)
|
|
1533
|
+
|
|
1534
|
+
# Добавляем фильтр по bot_id если указан
|
|
1535
|
+
if supabase_client.bot_id:
|
|
1536
|
+
query = query.eq("bot_id", supabase_client.bot_id)
|
|
1537
|
+
|
|
1538
|
+
query.execute()
|
|
1522
1539
|
logger.info(f"📝 Результат события {event_id} обновлен: {status}")
|
|
1523
1540
|
except Exception as e:
|
|
1524
1541
|
logger.error(f"❌ Ошибка обновления результата события {event_id}: {e}")
|
|
@@ -1613,7 +1630,14 @@ async def background_event_processor():
|
|
|
1613
1630
|
|
|
1614
1631
|
# ========== ОБРАБОТКА АДМИНСКИХ СОБЫТИЙ ==========
|
|
1615
1632
|
if event_category == "admin_event":
|
|
1633
|
+
# Проверяем bot_id
|
|
1634
|
+
if not event.get("bot_id"):
|
|
1635
|
+
logger.warning(f"⚠️ Админское событие {event['id']} не имеет bot_id")
|
|
1636
|
+
|
|
1616
1637
|
try:
|
|
1638
|
+
logger.info(f"🔄 Начало обработки админского события {event['id']}")
|
|
1639
|
+
logger.info(f"📝 Данные события: {event}")
|
|
1640
|
+
|
|
1617
1641
|
# Обрабатываем и получаем результат
|
|
1618
1642
|
result = await process_admin_event(event)
|
|
1619
1643
|
|
|
@@ -1621,22 +1645,37 @@ async def background_event_processor():
|
|
|
1621
1645
|
import json
|
|
1622
1646
|
|
|
1623
1647
|
supabase_client = get_supabase_client()
|
|
1624
|
-
supabase_client
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1648
|
+
if not supabase_client:
|
|
1649
|
+
raise RuntimeError("Не найден supabase_client")
|
|
1650
|
+
|
|
1651
|
+
# Готовим данные для обновления
|
|
1652
|
+
update_data = {
|
|
1653
|
+
"status": "completed",
|
|
1654
|
+
"executed_at": datetime.now(timezone.utc).isoformat(),
|
|
1655
|
+
"result_data": json.dumps(result, ensure_ascii=False) if result else None,
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
# Если у события нет bot_id, но он есть в клиенте - добавляем
|
|
1659
|
+
if not event.get("bot_id") and supabase_client.bot_id:
|
|
1660
|
+
update_data["bot_id"] = supabase_client.bot_id
|
|
1661
|
+
logger.info(f"📝 Добавлен bot_id: {supabase_client.bot_id}")
|
|
1662
|
+
|
|
1663
|
+
# Строим запрос
|
|
1664
|
+
query = (
|
|
1665
|
+
supabase_client.client.table("scheduled_events")
|
|
1666
|
+
.update(update_data)
|
|
1667
|
+
.eq("id", event["id"])
|
|
1668
|
+
)
|
|
1669
|
+
|
|
1670
|
+
# Добавляем фильтр по bot_id если он был в событии
|
|
1671
|
+
if event.get("bot_id"):
|
|
1672
|
+
query = query.eq("bot_id", event["bot_id"])
|
|
1673
|
+
|
|
1674
|
+
# Выполняем обновление
|
|
1675
|
+
query.execute()
|
|
1637
1676
|
|
|
1638
1677
|
logger.info(
|
|
1639
|
-
f"✅ Админское событие {event['id']} выполнено"
|
|
1678
|
+
f"✅ Админское событие {event['id']} выполнено и обновлено в БД"
|
|
1640
1679
|
)
|
|
1641
1680
|
continue
|
|
1642
1681
|
|
|
@@ -1644,18 +1683,45 @@ async def background_event_processor():
|
|
|
1644
1683
|
logger.error(
|
|
1645
1684
|
f"❌ Ошибка обработки админского события {event['id']}: {e}"
|
|
1646
1685
|
)
|
|
1686
|
+
logger.exception("Стек ошибки:")
|
|
1647
1687
|
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1688
|
+
try:
|
|
1689
|
+
# Обновляем статус на failed
|
|
1690
|
+
supabase_client = get_supabase_client()
|
|
1691
|
+
if not supabase_client:
|
|
1692
|
+
raise RuntimeError("Не найден supabase_client")
|
|
1693
|
+
|
|
1694
|
+
# Готовим данные для обновления
|
|
1695
|
+
update_data = {
|
|
1652
1696
|
"status": "failed",
|
|
1653
1697
|
"last_error": str(e),
|
|
1654
|
-
"executed_at": datetime.now(
|
|
1655
|
-
timezone.utc
|
|
1656
|
-
).isoformat(),
|
|
1698
|
+
"executed_at": datetime.now(timezone.utc).isoformat(),
|
|
1657
1699
|
}
|
|
1658
|
-
|
|
1700
|
+
|
|
1701
|
+
# Если у события нет bot_id, но он есть в клиенте - добавляем
|
|
1702
|
+
if not event.get("bot_id") and supabase_client.bot_id:
|
|
1703
|
+
update_data["bot_id"] = supabase_client.bot_id
|
|
1704
|
+
logger.info(f"📝 Добавлен bot_id: {supabase_client.bot_id}")
|
|
1705
|
+
|
|
1706
|
+
# Строим запрос
|
|
1707
|
+
query = (
|
|
1708
|
+
supabase_client.client.table("scheduled_events")
|
|
1709
|
+
.update(update_data)
|
|
1710
|
+
.eq("id", event["id"])
|
|
1711
|
+
)
|
|
1712
|
+
|
|
1713
|
+
# Добавляем фильтр по bot_id если он был в событии
|
|
1714
|
+
if event.get("bot_id"):
|
|
1715
|
+
query = query.eq("bot_id", event["bot_id"])
|
|
1716
|
+
|
|
1717
|
+
# Выполняем обновление
|
|
1718
|
+
query.execute()
|
|
1719
|
+
logger.info(f"✅ Статус события {event['id']} обновлен на failed")
|
|
1720
|
+
|
|
1721
|
+
except Exception as update_error:
|
|
1722
|
+
logger.error(f"❌ Ошибка обновления статуса события: {update_error}")
|
|
1723
|
+
logger.exception("Стек ошибки обновления:")
|
|
1724
|
+
|
|
1659
1725
|
continue
|
|
1660
1726
|
|
|
1661
1727
|
# ========== ОБРАБОТКА USER СОБЫТИЙ ==========
|
|
@@ -1820,7 +1886,27 @@ async def process_scheduled_event(event: Dict):
|
|
|
1820
1886
|
|
|
1821
1887
|
result = None
|
|
1822
1888
|
if event_category == "scheduled_task":
|
|
1889
|
+
# Получаем информацию о задаче
|
|
1890
|
+
router_manager = get_router_manager()
|
|
1891
|
+
if router_manager:
|
|
1892
|
+
scheduled_tasks = router_manager.get_scheduled_tasks()
|
|
1893
|
+
else:
|
|
1894
|
+
scheduled_tasks = _scheduled_tasks
|
|
1895
|
+
|
|
1896
|
+
task_info = scheduled_tasks.get(event_type, {})
|
|
1897
|
+
notify = task_info.get("notify", False)
|
|
1898
|
+
notify_time = task_info.get("notify_time", "after")
|
|
1899
|
+
|
|
1900
|
+
# Выполняем задачу
|
|
1823
1901
|
result = await execute_scheduled_task(event_type, user_id, event_data)
|
|
1902
|
+
|
|
1903
|
+
# Отправляем уведомление после выполнения если notify=True и notify_time="after"
|
|
1904
|
+
if notify and notify_time == "after":
|
|
1905
|
+
from ..core.bot_utils import notify_admins_about_event
|
|
1906
|
+
event_for_notify = {"тип": event_type, "инфо": event_data}
|
|
1907
|
+
await notify_admins_about_event(user_id, event_for_notify)
|
|
1908
|
+
logger.info(f" ✅ Админы уведомлены после выполнения задачи '{event_type}'")
|
|
1909
|
+
|
|
1824
1910
|
elif event_category == "global_handler":
|
|
1825
1911
|
result = await execute_global_handler(event_type, event_data)
|
|
1826
1912
|
elif event_category == "user_event":
|
|
@@ -7,6 +7,7 @@ import time
|
|
|
7
7
|
from datetime import datetime
|
|
8
8
|
from typing import Any, Dict, Optional
|
|
9
9
|
|
|
10
|
+
from aiogram.types import InlineKeyboardMarkup
|
|
10
11
|
import pytz
|
|
11
12
|
|
|
12
13
|
logger = logging.getLogger(__name__)
|
|
@@ -193,7 +194,7 @@ async def send_message_by_ai(
|
|
|
193
194
|
|
|
194
195
|
|
|
195
196
|
async def send_message_by_human(
|
|
196
|
-
user_id: int, message_text: str, session_id: Optional[str] = None
|
|
197
|
+
user_id: int, message_text: str, session_id: Optional[str] = None, parse_mode: str = "Markdown", reply_markup: Optional[InlineKeyboardMarkup] = None
|
|
197
198
|
) -> Dict[str, Any]:
|
|
198
199
|
"""
|
|
199
200
|
Отправляет сообщение пользователю от имени человека (готовый текст)
|
|
@@ -214,7 +215,7 @@ async def send_message_by_human(
|
|
|
214
215
|
supabase_client = get_global_var("supabase_client")
|
|
215
216
|
|
|
216
217
|
# Отправляем сообщение пользователю
|
|
217
|
-
message = await bot.send_message(chat_id=user_id, text=message_text)
|
|
218
|
+
message = await bot.send_message(chat_id=user_id, text=message_text, parse_mode=parse_mode, reply_markup=reply_markup)
|
|
218
219
|
|
|
219
220
|
# Если указана сессия, сохраняем сообщение в БД
|
|
220
221
|
if session_id:
|
smart_bot_factory/core/router.py
CHANGED
|
@@ -93,6 +93,7 @@ class EventRouter:
|
|
|
93
93
|
self,
|
|
94
94
|
task_name: str,
|
|
95
95
|
notify: bool = False,
|
|
96
|
+
notify_time: str = "after", # 'after' или 'before'
|
|
96
97
|
smart_check: bool = True,
|
|
97
98
|
once_only: bool = True,
|
|
98
99
|
delay: Union[str, int] = None,
|
|
@@ -105,6 +106,9 @@ class EventRouter:
|
|
|
105
106
|
Args:
|
|
106
107
|
task_name: Название задачи
|
|
107
108
|
notify: Уведомлять ли админов
|
|
109
|
+
notify_time: Когда отправлять уведомление админам:
|
|
110
|
+
- 'before': при создании задачи
|
|
111
|
+
- 'after': после успешного выполнения (по умолчанию)
|
|
108
112
|
smart_check: Использовать ли умную проверку
|
|
109
113
|
once_only: Выполнять ли только один раз
|
|
110
114
|
delay: Время задержки в удобном формате (например, "1h 30m", "45m", 3600) - ОБЯЗАТЕЛЬНО
|
|
@@ -141,10 +145,15 @@ class EventRouter:
|
|
|
141
145
|
)
|
|
142
146
|
raise
|
|
143
147
|
|
|
148
|
+
# Проверяем корректность notify_time
|
|
149
|
+
if notify_time not in ["before", "after"]:
|
|
150
|
+
raise ValueError(f"notify_time должен быть 'before' или 'after', получено: {notify_time}")
|
|
151
|
+
|
|
144
152
|
self._scheduled_tasks[task_name] = {
|
|
145
153
|
"handler": func,
|
|
146
154
|
"name": func.__name__,
|
|
147
155
|
"notify": notify,
|
|
156
|
+
"notify_time": notify_time, # Когда отправлять уведомление
|
|
148
157
|
"smart_check": smart_check,
|
|
149
158
|
"once_only": once_only,
|
|
150
159
|
"router": self.name,
|
|
@@ -95,9 +95,7 @@ async def timeup_handler(message: Message, state: FSMContext):
|
|
|
95
95
|
.in_("status", ["pending", "immediate"])
|
|
96
96
|
)
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
if supabase_client.bot_id:
|
|
100
|
-
user_events_query = user_events_query.eq("bot_id", supabase_client.bot_id)
|
|
98
|
+
user_events_query = user_events_query.eq("bot_id", supabase_client.bot_id)
|
|
101
99
|
|
|
102
100
|
user_events = user_events_query.execute()
|
|
103
101
|
|
|
@@ -107,14 +105,9 @@ async def timeup_handler(message: Message, state: FSMContext):
|
|
|
107
105
|
.select("*")
|
|
108
106
|
.is_("user_id", "null")
|
|
109
107
|
.in_("status", ["pending", "immediate"])
|
|
108
|
+
.eq("bot_id", supabase_client.bot_id)
|
|
110
109
|
)
|
|
111
110
|
|
|
112
|
-
# 🆕 Фильтруем по bot_id если указан
|
|
113
|
-
if supabase_client.bot_id:
|
|
114
|
-
global_events_query = global_events_query.eq(
|
|
115
|
-
"bot_id", supabase_client.bot_id
|
|
116
|
-
)
|
|
117
|
-
|
|
118
111
|
global_events = global_events_query.execute()
|
|
119
112
|
|
|
120
113
|
# Объединяем события
|
|
@@ -155,23 +148,25 @@ async def timeup_handler(message: Message, state: FSMContext):
|
|
|
155
148
|
)
|
|
156
149
|
|
|
157
150
|
# Выполняем событие
|
|
158
|
-
|
|
151
|
+
if event_category != "admin_event":
|
|
152
|
+
await process_scheduled_event(event)
|
|
159
153
|
|
|
160
154
|
# Помечаем как выполненное
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
155
|
+
if event_category != "admin_event" or event_category != "global_handler":
|
|
156
|
+
await update_event_result(
|
|
157
|
+
event_id,
|
|
158
|
+
"completed",
|
|
159
|
+
{
|
|
160
|
+
"executed": True,
|
|
161
|
+
"test_mode": True,
|
|
162
|
+
"tested_by_user": message.from_user.id,
|
|
163
|
+
"tested_at": datetime.now().isoformat(),
|
|
164
|
+
},
|
|
165
|
+
)
|
|
166
|
+
if event_category != "admin_event":
|
|
167
|
+
success_count += 1
|
|
168
|
+
results.append(f"✅ {event_label}")
|
|
169
|
+
logger.info(f"✅ Событие {event_id} успешно выполнено")
|
|
175
170
|
|
|
176
171
|
except Exception as e:
|
|
177
172
|
failed_count += 1
|
|
@@ -570,22 +570,37 @@ class SupabaseClient:
|
|
|
570
570
|
) -> int:
|
|
571
571
|
"""Начинает диалог между админом и пользователем"""
|
|
572
572
|
try:
|
|
573
|
+
# Проверяем существование пользователя с правильным bot_id
|
|
574
|
+
user_query = self.client.table("sales_users").select("telegram_id").eq("telegram_id", user_id)
|
|
575
|
+
if self.bot_id:
|
|
576
|
+
user_query = user_query.eq("bot_id", self.bot_id)
|
|
577
|
+
|
|
578
|
+
user_response = user_query.execute()
|
|
579
|
+
if not user_response.data:
|
|
580
|
+
logger.error(f"❌ Пользователь {user_id} не найден в sales_users{f' для bot_id {self.bot_id}' if self.bot_id else ''}")
|
|
581
|
+
raise APIError("User not found in sales_users")
|
|
582
|
+
|
|
573
583
|
# Завершаем активные диалоги этого админа
|
|
574
584
|
await self.end_admin_conversations(admin_id)
|
|
575
585
|
|
|
586
|
+
# Готовим данные для записи
|
|
587
|
+
conversation_data = {
|
|
588
|
+
"admin_id": admin_id,
|
|
589
|
+
"user_id": user_id,
|
|
590
|
+
"session_id": session_id,
|
|
591
|
+
"status": "active",
|
|
592
|
+
"auto_end_at": (
|
|
593
|
+
datetime.now(timezone.utc) + timedelta(minutes=30)
|
|
594
|
+
).isoformat(),
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
# Добавляем bot_id если он указан
|
|
598
|
+
if self.bot_id:
|
|
599
|
+
conversation_data["bot_id"] = self.bot_id
|
|
600
|
+
|
|
576
601
|
response = (
|
|
577
602
|
self.client.table("admin_user_conversations")
|
|
578
|
-
.insert(
|
|
579
|
-
{
|
|
580
|
-
"admin_id": admin_id,
|
|
581
|
-
"user_id": user_id,
|
|
582
|
-
"session_id": session_id,
|
|
583
|
-
"status": "active",
|
|
584
|
-
"auto_end_at": (
|
|
585
|
-
datetime.now(timezone.utc) + timedelta(minutes=30)
|
|
586
|
-
).isoformat(),
|
|
587
|
-
}
|
|
588
|
-
)
|
|
603
|
+
.insert(conversation_data)
|
|
589
604
|
.execute()
|
|
590
605
|
)
|
|
591
606
|
|
|
@@ -608,7 +623,7 @@ class SupabaseClient:
|
|
|
608
623
|
self.client.table("admin_user_conversations")
|
|
609
624
|
.update(
|
|
610
625
|
{
|
|
611
|
-
"status": "
|
|
626
|
+
"status": "completed", # Используем 'completed' вместо 'ended'
|
|
612
627
|
"ended_at": datetime.now(timezone.utc).isoformat(),
|
|
613
628
|
}
|
|
614
629
|
)
|
|
@@ -619,6 +634,9 @@ class SupabaseClient:
|
|
|
619
634
|
query = query.eq("admin_id", admin_id)
|
|
620
635
|
if user_id:
|
|
621
636
|
query = query.eq("user_id", user_id)
|
|
637
|
+
# Добавляем фильтр по bot_id если он указан
|
|
638
|
+
if self.bot_id:
|
|
639
|
+
query = query.eq("bot_id", self.bot_id)
|
|
622
640
|
|
|
623
641
|
response = query.execute()
|
|
624
642
|
ended_count = len(response.data)
|
|
@@ -1193,15 +1211,20 @@ class SupabaseClient:
|
|
|
1193
1211
|
"""Проверяет, изменился ли этап пользователя с момента планирования события"""
|
|
1194
1212
|
try:
|
|
1195
1213
|
# Получаем текущую информацию о сессии
|
|
1196
|
-
|
|
1214
|
+
query = (
|
|
1197
1215
|
self.client.table("sales_chat_sessions")
|
|
1198
1216
|
.select("id", "current_stage")
|
|
1199
|
-
.eq("
|
|
1217
|
+
.eq("user_id", user_id)
|
|
1200
1218
|
.order("created_at", desc=True)
|
|
1201
1219
|
.limit(1)
|
|
1202
|
-
.execute()
|
|
1203
1220
|
)
|
|
1204
1221
|
|
|
1222
|
+
# Добавляем фильтр по bot_id если он указан
|
|
1223
|
+
if self.bot_id:
|
|
1224
|
+
query = query.eq("bot_id", self.bot_id)
|
|
1225
|
+
|
|
1226
|
+
current_response = query.execute()
|
|
1227
|
+
|
|
1205
1228
|
if not current_response.data:
|
|
1206
1229
|
return False
|
|
1207
1230
|
|
|
@@ -1515,6 +1538,7 @@ class SupabaseClient:
|
|
|
1515
1538
|
|
|
1516
1539
|
scheduled_datetime = scheduled_datetime.replace(tzinfo=timezone.utc)
|
|
1517
1540
|
|
|
1541
|
+
# Готовим данные для записи
|
|
1518
1542
|
event_record = {
|
|
1519
1543
|
"event_type": event_name,
|
|
1520
1544
|
"event_category": "admin_event",
|
|
@@ -1524,6 +1548,11 @@ class SupabaseClient:
|
|
|
1524
1548
|
"status": "pending",
|
|
1525
1549
|
}
|
|
1526
1550
|
|
|
1551
|
+
# Добавляем bot_id если он указан
|
|
1552
|
+
if self.bot_id:
|
|
1553
|
+
event_record["bot_id"] = self.bot_id
|
|
1554
|
+
logger.info(f"📝 Добавлен bot_id: {self.bot_id} для админского события")
|
|
1555
|
+
|
|
1527
1556
|
response = (
|
|
1528
1557
|
self.client.table("scheduled_events").insert(event_record).execute()
|
|
1529
1558
|
)
|
|
@@ -1549,15 +1578,22 @@ class SupabaseClient:
|
|
|
1549
1578
|
List[Dict]: Список админских событий
|
|
1550
1579
|
"""
|
|
1551
1580
|
try:
|
|
1581
|
+
# Строим базовый запрос
|
|
1552
1582
|
query = (
|
|
1553
1583
|
self.client.table("scheduled_events")
|
|
1554
1584
|
.select("*")
|
|
1555
1585
|
.eq("event_category", "admin_event")
|
|
1556
1586
|
)
|
|
1557
1587
|
|
|
1588
|
+
# Добавляем фильтры
|
|
1558
1589
|
if status:
|
|
1559
1590
|
query = query.eq("status", status)
|
|
1560
1591
|
|
|
1592
|
+
# Фильтруем по bot_id если он указан
|
|
1593
|
+
if self.bot_id:
|
|
1594
|
+
query = query.eq("bot_id", self.bot_id)
|
|
1595
|
+
logger.info(f"🔍 Фильтруем админские события по bot_id: {self.bot_id}")
|
|
1596
|
+
|
|
1561
1597
|
response = query.order("scheduled_at", desc=False).execute()
|
|
1562
1598
|
|
|
1563
1599
|
logger.info(f"Найдено {len(response.data)} админских событий")
|
|
@@ -1578,15 +1614,22 @@ class SupabaseClient:
|
|
|
1578
1614
|
bool: True если активное событие с таким именем существует
|
|
1579
1615
|
"""
|
|
1580
1616
|
try:
|
|
1581
|
-
|
|
1617
|
+
# Строим запрос
|
|
1618
|
+
query = (
|
|
1582
1619
|
self.client.table("scheduled_events")
|
|
1583
1620
|
.select("id", "event_type", "status")
|
|
1584
1621
|
.eq("event_category", "admin_event")
|
|
1585
1622
|
.eq("event_type", event_name)
|
|
1586
1623
|
.eq("status", "pending")
|
|
1587
|
-
.execute()
|
|
1588
1624
|
)
|
|
1589
1625
|
|
|
1626
|
+
# Фильтруем по bot_id если он указан
|
|
1627
|
+
if self.bot_id:
|
|
1628
|
+
query = query.eq("bot_id", self.bot_id)
|
|
1629
|
+
logger.info(f"🔍 Проверка названия события с фильтром по bot_id: {self.bot_id}")
|
|
1630
|
+
|
|
1631
|
+
response = query.execute()
|
|
1632
|
+
|
|
1590
1633
|
exists = len(response.data) > 0
|
|
1591
1634
|
|
|
1592
1635
|
if exists:
|
|
@@ -6,7 +6,7 @@ smart_bot_factory/utm_link_generator.py,sha256=eA3Eic4Wvs0QpMdAFPJgYJyzv-_pSQWZ5
|
|
|
6
6
|
smart_bot_factory/admin/__init__.py,sha256=xHUtMLeQDDQEXZrg4WAGpt-TWp8adjCC0-mYUBuino4,489
|
|
7
7
|
smart_bot_factory/admin/admin_events.py,sha256=FkiD0FtnlgpxLCoN9KXR61VCn8OsI0JCWm9RjVVa6tk,43903
|
|
8
8
|
smart_bot_factory/admin/admin_logic.py,sha256=TiXhZIXiXK1YQkrueY_zPFYL3_sJzoAvd100AP-ZCWU,23136
|
|
9
|
-
smart_bot_factory/admin/admin_manager.py,sha256=
|
|
9
|
+
smart_bot_factory/admin/admin_manager.py,sha256=u22j1xy2zLTw0kejgzWF5m657_IyMDKnDlM9kBzbjh4,6359
|
|
10
10
|
smart_bot_factory/admin/admin_tester.py,sha256=YwovS51chPJoQ33pIiug-vS3augQzc1hHfbma48HtDk,6352
|
|
11
11
|
smart_bot_factory/admin/timeout_checker.py,sha256=afWsg39X6M5SaRKMk7ptNod8Z0StIa2o8H5Lx8y1ZE0,24438
|
|
12
12
|
smart_bot_factory/aiogram_calendar/__init__.py,sha256=UCoae3mXXDgYqqSQPotEpUxzAsZ_e62FuW9MWl1sG34,410
|
|
@@ -29,11 +29,11 @@ smart_bot_factory/configs/growthmed-october-24/tests/realistic_scenarios.yaml,sh
|
|
|
29
29
|
smart_bot_factory/configs/growthmed-october-24/tests/scenario_examples.yaml,sha256=bzDulOU4a2LyWlcHzlQU8GYhOky2WTfyizGfjX4ioMY,2436
|
|
30
30
|
smart_bot_factory/configs/growthmed-october-24/welcome_file/welcome_file_msg.txt,sha256=Db21Mm0r8SBWFdX9EeIF2FZtLQ2cvuwVlSRJd2KEYCg,922
|
|
31
31
|
smart_bot_factory/configs/growthmed-october-24/welcome_file/Чек лист по 152ФЗ и 323ФЗ для медицины.pdf,sha256=BiAiQHNnQXJPMsks9AeL6s0beEjRFkRMJLMlAn4WorA,5284954
|
|
32
|
-
smart_bot_factory/core/bot_utils.py,sha256=
|
|
33
|
-
smart_bot_factory/core/conversation_manager.py,sha256=
|
|
34
|
-
smart_bot_factory/core/decorators.py,sha256=
|
|
35
|
-
smart_bot_factory/core/message_sender.py,sha256=
|
|
36
|
-
smart_bot_factory/core/router.py,sha256=
|
|
32
|
+
smart_bot_factory/core/bot_utils.py,sha256=vbWb4wUkG-FlQIGTQ6RLoSSVg_LRVTzpnX3tyowsbqY,52032
|
|
33
|
+
smart_bot_factory/core/conversation_manager.py,sha256=ga0ThoDpvov97x5KLcHpL8aRlEZB1XRw3JPrexIb-jk,29506
|
|
34
|
+
smart_bot_factory/core/decorators.py,sha256=1FwJMjSM-QEgX3hX_LEW0A6VS3TWXBRIwwpPxK2pZuA,108247
|
|
35
|
+
smart_bot_factory/core/message_sender.py,sha256=gK0HbjLumAu5_Vr29DnOQkwbPGGmQrtkgW1dVt_9Bb8,32518
|
|
36
|
+
smart_bot_factory/core/router.py,sha256=66sCp7Okyu1ceIQPpxFF88-NizTD1N7rR4ZAdwDYmi8,16285
|
|
37
37
|
smart_bot_factory/core/router_manager.py,sha256=x-cc4zhZUVPCTUH980GdlE_-JjHRtYnPdEBiWnf3ka8,10156
|
|
38
38
|
smart_bot_factory/core/states.py,sha256=mFyQ-oxIjTX03Wy5NHZUgYgh8fsJ5YmQU09_PhPAB04,889
|
|
39
39
|
smart_bot_factory/creation/__init__.py,sha256=lHFgYIjOLvdsDAW8eLMp8zfFUCd-6wepvUaUMeJ7feU,128
|
|
@@ -41,9 +41,9 @@ smart_bot_factory/creation/bot_builder.py,sha256=-gF53eCaWBRKoUbRGR-PDHpqLWlceQ9
|
|
|
41
41
|
smart_bot_factory/creation/bot_testing.py,sha256=aMPSgj2o2zl6yWiV1a6RMmSJfiwMYp-_0ZkmJ6aFZVs,54561
|
|
42
42
|
smart_bot_factory/dashboard/__init__.py,sha256=Qie1pJgzprBlCPrZVQLhVs1JR5-YrpzfcBvHHD3OLJk,94
|
|
43
43
|
smart_bot_factory/event/__init__.py,sha256=E5u8Pjul_T0E77Ftmj-mqrip05w7KwUXlF1WMc5_lIs,192
|
|
44
|
-
smart_bot_factory/handlers/handlers.py,sha256=
|
|
44
|
+
smart_bot_factory/handlers/handlers.py,sha256=za41yxSfsSwARnuI-l57JO90HN2knOXIqkbgq_z-MOA,63623
|
|
45
45
|
smart_bot_factory/integrations/openai_client.py,sha256=R04qglOWNu3yQ32QRMRMzO01T6luWTp83H3OJMvD-uM,24316
|
|
46
|
-
smart_bot_factory/integrations/supabase_client.py,sha256=
|
|
46
|
+
smart_bot_factory/integrations/supabase_client.py,sha256=7Yip9din4PDqFD1X2pkKB4KYAhmf04LUzxo9SnOrVg4,68415
|
|
47
47
|
smart_bot_factory/message/__init__.py,sha256=neUUYAs8ITz3cV1B_T0P9_3XZvvn8cZ2VDpDqrf6lrc,1940
|
|
48
48
|
smart_bot_factory/router/__init__.py,sha256=ywywG6iFBLLkBvtZ-huPVetqjXGN4UiUzoK6lw46bMg,272
|
|
49
49
|
smart_bot_factory/supabase/__init__.py,sha256=xa1xmHLaQVoghjD5cqguiL4yd25VYMvGd6_e87uc0tQ,181
|
|
@@ -52,8 +52,8 @@ smart_bot_factory/utils/__init__.py,sha256=RgP2IAMFsJF7fxhhg8JLfhbGg9mO63xQM-NEa
|
|
|
52
52
|
smart_bot_factory/utils/debug_routing.py,sha256=wV9BFwNmjBbF3rNI7UBdGsTf1bIT5XVQIGnxwIxhNYA,4707
|
|
53
53
|
smart_bot_factory/utils/prompt_loader.py,sha256=YClbQjvRgTWCD42Rr92g77zzVEVMUgrqStI6YETC0c4,20022
|
|
54
54
|
smart_bot_factory/utils/user_prompt_loader.py,sha256=lq1eQ4Hb2qN22osOjaFtkGdEc4OgpFPrzPNpPhsm5kA,2353
|
|
55
|
-
smart_bot_factory-0.3.
|
|
56
|
-
smart_bot_factory-0.3.
|
|
57
|
-
smart_bot_factory-0.3.
|
|
58
|
-
smart_bot_factory-0.3.
|
|
59
|
-
smart_bot_factory-0.3.
|
|
55
|
+
smart_bot_factory-0.3.10.dist-info/METADATA,sha256=1rn8juhuHmHF0Vf9tmqucWYj0JW-acIjzvIMlvLfvFI,40749
|
|
56
|
+
smart_bot_factory-0.3.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
57
|
+
smart_bot_factory-0.3.10.dist-info/entry_points.txt,sha256=ybKEAI0WSb7WoRiey7QE-HHfn88UGV7nxLDxXq7b7SU,50
|
|
58
|
+
smart_bot_factory-0.3.10.dist-info/licenses/LICENSE,sha256=OrK3cwdUTzNzIhJvSPtJaVMoYIyC_sSx5EFE_FDMvGs,1092
|
|
59
|
+
smart_bot_factory-0.3.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|