Files
angel 72b6879f4b v1.7.0: refactor max_bot to flat structure, add VCF+UserModel+NLP history context, portal pages and proxy fixes
- Refactored max_bot from nested packages to flat module structure
- Q2: Extended BotUser model (patronymic, email, org, address, vcf_raw, contact_hash, phone_verified, email_verified, last_interaction, total_conversations, total_tickets)
- Q2: VCF parser (FN, N, TEL, EMAIL, ORG, ADR), upsert on re-contact, NLP history context (_get_user_history_context -> YandexGPT)
- Q1: Broadcast preview modal with 10s confirmation timer
- Q3: CSS var(--white)->var(--bg-card), var(--text)->var(--text-primary)
- Q4: bot_settings showNotification(), editable max_bot_id
- Q5: Webhook secret passthrough via X-Max-Bot-Api-Secret
- Masking sensitive keys, dialog_cleared handler, migrate via _add_column_if_not_exists()
- Rate limit (asyncio.sleep 0.5 per 10), dead code removed, conv.intent context in contact.py
- Portal pages: bot_consent, bot_kb (edit), bot_settings, bot_test, bot_tickets, portal_settings
- Tests: 21/21 passing, added test_yandex_gpt.py, test_email_sender.py
- Deploy: deploy_full.sh, schema.sql, seed_knowledge_base.sql
2026-05-29 02:30:30 +03:00

70 lines
3.9 KiB
PHP

<?php
/**
* AegisOne Engineering — Установка / обновление базы данных
*
* Запускает миграцию из data/migration.sql
* Безопасно при повторном запуске (IF NOT EXISTS, ON DUPLICATE KEY UPDATE)
*/
require_once __DIR__ . '/../data/db-config.php';
try {
if (DB_TYPE === 'pgsql') {
$dsn = 'pgsql:host=' . DB_HOST . ';port=' . DB_PORT . ';dbname=' . DB_NAME;
} else {
$dsn = 'mysql:host=' . DB_HOST . ';port=' . DB_PORT . ';dbname=' . DB_NAME . ';charset=' . DB_CHARSET;
}
$pdo = new PDO(
$dsn,
DB_USER,
DB_PASS,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
$sqlPath = DB_TYPE === 'pgsql'
? __DIR__ . '/../py_service/sql/schema_postgresql.sql'
: __DIR__ . '/../data/migration.sql';
$sql = file_get_contents($sqlPath);
$statements = array_filter(array_map('trim', explode(';', $sql)));
$created = 0;
$inserted = 0;
$errors = 0;
foreach ($statements as $query) {
if ($query === '' || strpos($query, '--') === 0) continue;
try {
$pdo->exec($query);
if (stripos($query, 'CREATE') !== false) $created++;
if (stripos($query, 'INSERT') !== false) $inserted++;
} catch (\Throwable $e) {
$errors++;
}
}
echo '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Миграция — AegisOne</title>';
echo '<style>body{font-family:Inter,sans-serif;background:#0D1B2A;color:#E8EDF2;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;}';
echo '.box{background:#1B2838;border:1px solid #2a3a4a;border-radius:12px;padding:40px;max-width:500px;text-align:center;}';
echo 'h1{color:#4DA8DA;margin:0 0 8px;font-size:22px;}p{color:#A0B4C8;font-size:14px;margin:0 0 20px;line-height:1.6;}';
echo '.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:20px 0;}';
echo '.stat{background:#0D1B2A;border-radius:8px;padding:16px;text-align:center;}';
echo '.stat-value{font-size:28px;font-weight:700;color:#00ADEF;}';
echo '.stat-label{font-size:11px;color:#6B8299;text-transform:uppercase;letter-spacing:0.1em;margin-top:4px;}';
echo '.btn{display:inline-block;background:linear-gradient(135deg,#00ADEF,#0095cc);color:#fff;padding:12px 28px;border-radius:8px;text-decoration:none;font-weight:600;font-size:14px;margin-top:16px;}';
echo '</style></head><body><div class="box">';
echo '<h1>✅ Миграция завершена</h1>';
echo '<p>База данных <strong>' . htmlspecialchars(DB_NAME) . '</strong> обновлена.</p>';
echo '<div class="stats">';
echo '<div class="stat"><div class="stat-value">' . $created . '</div><div class="stat-label">Таблиц</div></div>';
echo '<div class="stat"><div class="stat-value">' . $inserted . '</div><div class="stat-label">Записей</div></div>';
echo '<div class="stat"><div class="stat-value">' . $errors . '</div><div class="stat-label">Ошибок</div></div>';
echo '</div>';
echo '<a href="/service/" class="btn">Войти в систему</a>';
echo '</div></body></html>';
} catch (\Throwable $e) {
echo '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Ошибка — AegisOne</title>';
echo '<style>body{font-family:Inter,sans-serif;background:#0D1B2A;color:#E8EDF2;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;}';
echo '.box{background:#1B2838;border:1px solid #ef4444;border-radius:12px;padding:40px;max-width:500px;text-align:center;}';
echo 'h1{color:#ef4444;margin:0 0 8px;font-size:22px;}p{color:#A0B4C8;font-size:14px;line-height:1.6;}</style></head><body>';
echo '<div class="box"><h1>❌ Ошибка подключения</h1><p>' . htmlspecialchars($e->getMessage()) . '</p></div></body></html>';
}