72b6879f4b
- 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
129 lines
5.8 KiB
Markdown
129 lines
5.8 KiB
Markdown
# MAX Bot Fixes — Implementation Plan v2
|
|
|
|
## Phase 1: py_service (no rebuild, restart only)
|
|
|
|
### 1a. Fix ctx() mojibake
|
|
**File:** `py_service/app/routers/service_pages.py:48`
|
|
```python
|
|
# Add to ctx() dict:
|
|
"page_name": kw.get("active_page", "")
|
|
```
|
|
|
|
### 1b. Add broadcast page route
|
|
**File:** `py_service/app/routers/service_pages.py` — after line 1396:
|
|
```python
|
|
@router.get("/service/bot-settings/broadcasts")
|
|
async def bot_broadcasts_page(request, db, user):
|
|
return templates.TemplateResponse("pages/bot_broadcasts.html", ctx(request, user=user, active_page="bot-broadcasts", title="Рассылки"))
|
|
```
|
|
Plus proxy endpoints for broadcast data.
|
|
|
|
### 1c. Add sidebar link
|
|
**File:** `py_service/app/templates/_sidebar.html` — after bot-storage line:
|
|
```html
|
|
{% if role_permissions.get('bot_broadcasts', True) != False %}<a href="/service/bot-settings/broadcasts" class="{% if active_page == 'bot-broadcasts' %}active{% endif %}">Рассылки</a>{% endif %}
|
|
```
|
|
|
|
### 1d. Create bot_broadcasts.html template
|
|
**File:** `py_service/app/templates/pages/bot_broadcasts.html`
|
|
Basically the broadcast section extracted from bot_analytics.html into its own page.
|
|
|
|
### 1e. Add try/except to all proxy endpoints
|
|
**File:** `py_service/app/routers/service_pages.py`
|
|
Create helper:
|
|
```python
|
|
async def _proxy(method, path, json_body=None):
|
|
try:
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.request(method, f"{MAX_BOT_URL}{path}", json=json_body) as resp:
|
|
return JSONResponse(await resp.json())
|
|
except Exception as e:
|
|
return JSONResponse({"error": f"Bot service unavailable: {e}", "ok": False}, status_code=503)
|
|
```
|
|
|
|
### 1f. Update permission_config.py
|
|
Add ALL missing routes (bot broadcasts, notifications, handoffs, risk-questions, storage, tickets)
|
|
|
|
## Phase 2: max_bot (rebuild required)
|
|
|
|
### 2a. Fix feature_key auto_notifications → notifications
|
|
**File:** `max_bot/sql/bot_schema.sql:156` — change `'auto_notifications'` to `'notifications'`
|
|
|
|
### 2b. Fix commercial_offer → commercial (or vice versa)
|
|
**File:** `max_bot/sql/bot_schema.sql:153` — change `'commercial_offer'` to `'commercial'`
|
|
**File:** `max_bot/app/keyboards/inline.py:20` — ensure payload matches
|
|
|
|
### 2c. Fix test-run: add role:'bot' to test messages
|
|
**File:** `max_bot/app/max_api.py:71` — add `msg["role"] = "bot"`
|
|
**File:** `max_bot/app/main.py:407` — add `role: 'bot'` when copying greeting
|
|
|
|
### 2d. Fix flush→commit everywhere
|
|
**Files:** `max_bot/app/main.py`
|
|
- Lines 596, 620, 632, 644 → `db.commit()`
|
|
- Lines 722, 725 → `db.commit()`
|
|
- Lines 740, 755 → `db.commit()`
|
|
- Lines 801, 814 → `db.commit()`
|
|
- Line 852 → `db.commit()`
|
|
|
|
**File:** `max_bot/app/database.py:15-17` — add session.commit():
|
|
```python
|
|
async def get_db():
|
|
async with async_session() as session:
|
|
try:
|
|
yield session
|
|
await session.commit()
|
|
except Exception:
|
|
await session.rollback()
|
|
raise
|
|
```
|
|
|
|
### 2e. SQL migration: add recipient_ids to bot_broadcasts
|
|
**File:** `max_bot/sql/migrations/v1.6.0_fixes.sql`
|
|
```sql
|
|
ALTER TABLE bot_broadcasts ADD COLUMN IF NOT EXISTS recipient_ids JSONB DEFAULT '[]'::jsonb;
|
|
```
|
|
|
|
### 2f. FSM persistence (optional)
|
|
Create `bot_fsm_states` table + async save/load in FSM class.
|
|
|
|
### 2g. RMP permissions for engineer (optional)
|
|
Add INSERT for engineer with bot_* menu keys.
|
|
|
|
## Phase 3: Replace categories
|
|
|
|
### 3a. SQL migration:
|
|
```sql
|
|
DELETE FROM bot_categories;
|
|
INSERT INTO bot_categories (name, description, icon_emoji, keywords, sort_order) VALUES
|
|
('Аудит безопасности', 'Независимая оценка систем видеонаблюдения, СКУД, ОПС', '🔍', '["аудит","безопасность","оценка","видеонаблюдение","скуд","опс"]', 1),
|
|
('Сервисное обслуживание / SLA', 'Абонентское обслуживание по SLA-контракту', '🛡️', '["сервис","sla","абонентский","обслуживание","контракт"]', 2),
|
|
('Реагирование на инциденты', 'Срочное реагирование при нештатных ситуациях', '🚨', '["инцидент","реагирование","срочный","нештатный","авария"]', 3),
|
|
('Технический надзор', 'Контроль качества при монтаже и пусконаладке', '📐', '["надзор","технический","контроль","качество","монтаж","пусконаладка"]', 4),
|
|
('Проектная документация', 'Разработка и согласование проектной документации', '📄', '["проект","документация","разработка","согласование"]', 5),
|
|
('Риск-инжиниринг', 'Оценка рисков, BCP, DRP, стратегия безопасности', '⚡', '["риск","инжиниринг","bcp","drp","стратегия","безопасность"]', 6),
|
|
('Общий вопрос', 'Консультация или вопрос вне указанных категорий', '💬', '["консультация","вопрос","общий","другое"]', 7);
|
|
```
|
|
|
|
## Phase 4: Deploy scripts
|
|
|
|
### 4a. Fix max_bot_deploy.sh rsync
|
|
**File:** `max_bot/max_bot_deploy.sh:32` — change `max_bot/` to `.`
|
|
|
|
### 4b. Add max_bot hook to main deploy.sh
|
|
**File:** `py_service/deploy.sh` — after docker compose up -d:
|
|
```bash
|
|
echo "Deploying max_bot..."
|
|
bash max_bot/max_bot_deploy.sh
|
|
```
|
|
|
|
## Phase 5: Changelog
|
|
Create `CHANGELOG.md` with all fixes.
|
|
|
|
## Deploy Order
|
|
1. SQL migrations on DB
|
|
2. scp + docker exec tee for py_service files
|
|
3. docker compose restart aegisone-app
|
|
4. scp + docker compose build for max_bot
|
|
5. docker compose up -d aegisone-max-bot
|
|
6. Verify health checks
|