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
This commit is contained in:
2026-05-29 02:30:30 +03:00
parent 493e0b37a1
commit 72b6879f4b
234 changed files with 26768 additions and 6240 deletions
+50 -92
View File
@@ -1,106 +1,64 @@
#!/bin/bash
# ==========================================
# MAX Bot — Deploy Script
# ==========================================
# AegisOne MAX Bot — Deploy Script
# Usage: bash max_bot_deploy.sh
# Run on VPS as angel user (or from local with SSH)
set -e
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
log() { echo -e "${CYAN}[$(date +%H:%M:%S)]${NC} $1"; }
ok() { echo -e " ${GREEN}$1${NC}"; }
info() { echo -e " ${YELLOW}$1${NC}"; }
fail() { echo -e " ${RED}$1${NC}"; exit 1; }
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="/opt/projects/aegisone-py"
REMOTE_USER="angel"
REMOTE_HOST="81.177.141.34"
cd "$(dirname "$0")"
echo "=== MAX Bot Deploy ==="
echo "Building and packaging max_bot..."
echo -e "${CYAN}"
echo "=========================================="
echo " MAX Bot — Deploy"
echo "=========================================="
echo -e "${NC}"
cd "$SCRIPT_DIR"
BOT="/opt/projects/aegisone-py/max_bot"
PY="/opt/projects/aegisone-py"
NGX="/opt/projects/nginx-proxy"
# Create tar archive
cd "$PROJECT_DIR"
tar czf /tmp/max_bot_update.tar.gz \
-C "$SCRIPT_DIR/.." max_bot/ \
--exclude max_bot/__pycache__ \
--exclude max_bot/.pytest_cache \
--exclude "max_bot/*.pyc" \
--exclude max_bot/tests
# ==========================================
# 1. Deploy max_bot files
# ==========================================
log "Deploying max_bot files..."
mkdir -p "$BOT"
rsync -a --delete ./ "$BOT/" 2>/dev/null || cp -r ./* "$BOT/"
ok "Files deployed to $BOT"
echo "Copying to server..."
scp /tmp/max_bot_update.tar.gz "$REMOTE_USER@$REMOTE_HOST:/tmp/"
ssh "$REMOTE_USER@$REMOTE_HOST" << 'EOF'
set -e
PROJECT="/opt/projects/aegisone-py/max_bot"
BACKUP="/opt/projects/backups/max_bot_$(date +%Y%m%d_%H%M%S)"
# ==========================================
# 2. Deploy nginx config
# ==========================================
log "Deploying nginx config for max.aegisone.ru..."
cp max_bot/nginx/max-aegisone.conf "$NGX/conf.d/max-aegisone.conf"
docker compose -f "$NGX/docker-compose.yml" exec nginx nginx -s reload 2>/dev/null || true
ok "Nginx reloaded"
echo "Creating backup..."
if [ -d "$PROJECT" ]; then
mkdir -p "/opt/projects/backups"
cp -a "$PROJECT" "$BACKUP"
fi
# ==========================================
# 3. Run SQL migrations
# ==========================================
PG_CONTAINER=$(docker ps --filter "name=aegisone-postgres" --format "{{.ID}}" | head -1)
if [ -n "$PG_CONTAINER" ]; then
log "Running SQL migration v1.5.0..."
cat "$PY/sql/v1.5.0_migration.sql" 2>/dev/null | docker exec -i "$PG_CONTAINER" psql -U aegisone -d aegisone 2>&1 | grep -v "^INSERT\|^CREATE\|^ALTER\|^CREATE INDEX" || true
ok "SQL migration v1.5.0 applied"
echo "Extracting update..."
mkdir -p "$PROJECT"
tar xzf /tmp/max_bot_update.tar.gz -C /opt/projects/aegisone-py/
log "Running SQL migration v1.5.2..."
cat "$BOT/sql/migrations/v1.5.2_role_menu_permissions.sql" 2>/dev/null | docker exec -i "$PG_CONTAINER" psql -U aegisone -d aegisone 2>&1 | grep -v "^INSERT\|^CREATE\|^ALTER\|^CREATE INDEX" || true
ok "SQL migration v1.5.2 applied"
echo "Rebuilding and restarting container..."
cd "$PROJECT"
docker compose down 2>/dev/null || true
docker compose build --no-cache --network host
docker compose up -d
log "Running SQL migration v1.5.5..."
cat "$BOT/sql/migrations/v1.5.5_tables_and_seed.sql" 2>/dev/null | docker exec -i "$PG_CONTAINER" psql -U aegisone -d aegisone 2>&1 | grep -v "^INSERT\|^CREATE\|^ALTER\|^CREATE INDEX" || true
ok "SQL migration v1.5.5 applied"
else
info "PostgreSQL container not found — run migration manually"
fi
echo "Checking health..."
sleep 5
for i in 1 2 3 4 5; do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://max.aegisone.ru/health || echo "000")
if [ "$HTTP_CODE" = "200" ]; then
echo "Health check PASSED (HTTP $HTTP_CODE)"
break
fi
echo "Waiting... attempt $i/5"
sleep 3
done
# ==========================================
# 4. Run SQL migration v1.6.0 via docker exec pipe
# ==========================================
PG_CONTAINER=$(docker ps --filter "name=aegisone-postgres" --format "{{.ID}}" | head -1)
if [ -n "$PG_CONTAINER" ]; then
log "Running SQL migration v1.6.0..."
cat "$BOT/sql/migrations/v1.6.0_fixes.sql" | docker exec -i "$PG_CONTAINER" psql -U aegisone -d aegisone 2>&1 | grep -v "^INSERT\|^UPDATE\|^DELETE\|^ALTER TABLE\|^CREATE INDEX\|^DROP VIEW" || true
ok "SQL migration v1.6.0 applied"
else
info "PostgreSQL container not found — run migration manually"
fi
echo "Deploy complete!"
EOF
# ==========================================
# 5. Build & start max_bot
# ==========================================
log "Building and starting max_bot..."
cd "$BOT" && docker compose up -d --build
ok "max_bot started on port 8002"
# ==========================================
# 6. Health check
# ==========================================
log "Checking health..."
sleep 3
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8002/health 2>/dev/null || echo "000")
if [ "$HTTP_CODE" = "200" ]; then
ok "max_bot is healthy (HTTP $HTTP_CODE)"
else
info "Health check returned HTTP $HTTP_CODE — check logs: docker logs aegisone-max-bot"
fi
# ==========================================
# Done
# ==========================================
echo ""
echo -e "${GREEN}=========================================="
echo " MAX Bot deploy complete!"
echo "==========================================${NC}"
echo ""
echo " Bot webhook: https://max.aegisone.ru/webhook"
echo " Bot API: https://max.aegisone.ru/api/"
echo " Health check: http://localhost:8002/health"
echo " Logs: docker logs -f aegisone-max-bot"
echo ""
echo "=== Done ==="