surfaces/docs/research/telegram-chat-alternatives.md
Mikhail Putilovskij 67499daa61 feat: extend platform mock + add research docs
platform/interface.py:
- Add Attachment, MessageChunk, AgentEvent types
- Add stream_message() to PlatformClient Protocol (door open for streaming)
- Add WebhookReceiver Protocol

platform/mock.py:
- Add attachment_mode config (url/binary/s3)
- Implement stream_message() — single chunk, ready for real streaming
- Add register_webhook_receiver() + simulate_agent_event() for testing

docs/research/:
- telegram-forum-topics.md — aiogram 3.x Forum Topics API, FSM patterns, UX analysis
- fsm-patterns.md — FSM storage options, StateData best practices
- matrix-spaces.md — matrix-nio Space API, room ordering, invite flow
- matrix-events.md — reactions, threads, typing, sync loop pitfalls
- telegram-chat-alternatives.md — 7 alternatives for multi-chat UX, virtual chats in DM recommended
2026-03-30 14:04:34 +03:00

251 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Research: Альтернативные варианты организации чатов в Telegram
## Сравнительная таблица
| Вариант | Friction для юзера | Техническая сложность | Ограничения | Статус |
|---------|-------------------|----------------------|-------------|--------|
| **1. Виртуальные чаты в DM** | Нет | Низкая | Нет | ✅ РЕКОМЕНДУЕТСЯ |
| **2. Threads / Reply Threads** | Высокая | Средняя | Требует группу, бот не создаёт темы | ❌ |
| **3. Multiple Bot Instances** | Высокая | Средняя | Нужно добавлять каждый | ❌ |
| **4. Inline Mode** | Нет | Низкая | Stateless, не для диалогов | ❌ |
| **5. Бот создаёт приватные группы** | Очень высокая | Очень высокая | Bot API не создаёт группы | ❌ |
| **6. Telegram Web App (TWA)** | Нет | Высокая | Нужен web-сервер | ⚠️ Phase 2 |
| **7. Forum Topics (исходный)** | Высокая | Средняя | Пользователь создаёт группу вручную | ⚠️ Оставить как опцию |
---
## Вариант 1: Виртуальные чаты в DM (РЕКОМЕНДУЕТСЯ)
### Как выглядит для пользователя
```
/start
→ [ Новый чат] [📋 Мои чаты] [⚙️ Настройки]
Нажимает "Новый чат"
→ "✅ Чат #1 создан! Начните писать..."
User: "Расскажи про Python"
→ "[Чат #1] Python — это язык программирования..."
Нажимает "Мои чаты"
→ 1⃣ Чат #1 (Python)
2⃣ Чат #2 (Математика) — 2 часа назад
3⃣ Исследование рынка — вчера
Нажимает на "Чат #2"
→ "Вы в Чате #2. Последние сообщения: ..."
→ Продолжает разговор
```
### Технические детали (aiogram 3.x)
#### FSM состояния
```python
from aiogram.fsm.state import State, StatesGroup
class UserStates(StatesGroup):
main_menu = State()
in_chat = State()
selecting_chat = State()
```
#### Хранение активного чата в StateData
```python
# При создании чата
await state.set_state(UserStates.in_chat)
await state.update_data(active_chat_id=chat_id)
# При получении сообщения
data = await state.get_data()
chat_id = data["active_chat_id"]
```
#### Список чатов с инлайн-кнопками
```python
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
@router.message(Command("list"))
async def cmd_list(message: Message, state: FSMContext):
chats = db.get_user_chats(message.from_user.id)
buttons = [
[InlineKeyboardButton(
text=f"📄 {chat.title or f'Чат #{chat.id[:6]}'}",
callback_data=f"select:{chat.id}"
)]
for chat in chats
]
await message.answer("📋 Ваши чаты:", reply_markup=InlineKeyboardMarkup(inline_keyboard=buttons))
@router.callback_query(F.data.startswith("select:"))
async def switch_chat(callback: CallbackQuery, state: FSMContext):
chat_id = callback.data.split(":")[1]
await state.update_data(active_chat_id=chat_id)
await state.set_state(UserStates.in_chat)
await callback.message.edit_text(f"✅ Переключился в чат. Пишите...")
```
#### Схема БД
```sql
CREATE TABLE chats (
chat_id TEXT PRIMARY KEY, -- UUID
user_id INTEGER NOT NULL,
title TEXT,
created_at TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TABLE messages (
id INTEGER PRIMARY KEY,
chat_id TEXT NOT NULL,
user_id INTEGER NOT NULL,
direction TEXT, -- 'user' / 'bot'
content TEXT NOT NULL,
created_at TIMESTAMP,
FOREIGN KEY(chat_id) REFERENCES chats(chat_id)
);
```
### Ограничения
- История только в нашей БД, не в Telegram нативно
- Нет шаринга чата с другими пользователями
### Примеры в реальных ботах
- **ChatGPT Telegram боты** — именно этот паттерн, `/new` → новый разговор, `/history` → список
- **StudyGPT** — каждый урок = отдельный "чат" с контекстом
- **Notion Bot** — список "проектов" с переключением
### Оценка
✅ Нулевое трение — ничего настраивать не нужно
✅ Работает в DM — приватно
✅ Стандартный паттерн — пользователи знакомы
✅ Полный контроль над UX
✅ Масштабируется без ограничений
❌ История только в нашей БД (но это нормально)
---
## Вариант 2: Threads / Reply Topics — ОТКЛОНЕНО
### Суть
Telegram поддерживает `message_thread_id` в апдейтах — можно читать из какого треда пришло сообщение и отвечать в него. Но:
- **Бот не может создавать треды** — Bot API этого не умеет
- Работает только в Group/Supergroup, не в DM
- Пользователь должен создавать каждый тред вручную
- Не решает проблему friction — делает хуже
```python
# Читать можно
thread_id = message.message_thread_id # int или None
# Отвечать можно
await message.answer("ответ", message_thread_id=thread_id)
# Создать тред НЕЛЬЗЯ — метода нет в Bot API
```
---
## Вариант 3: Deep Linking — ОТКЛОНЕНО
Каждый чат = отдельная ссылка вида `https://t.me/bot?start=chatid_xyz`. Пользователь переходит по ссылке, бот предвыбирает чат.
**Проблема:** пользователь не знает что такие ссылки существуют, нет discovery, не масштабируется.
```python
@router.message(Command("start"))
async def cmd_start(message: Message):
args = message.text.split()
if len(args) > 1:
chat_id = args[1] # из deep link
# предвыбрать чат
```
---
## Вариант 4: Inline Mode — ОТКЛОНЕНО
Inline mode (`@botname query`) — fundamentally stateless. Один запрос → несколько результатов → пользователь выбирает. Нет истории, нет контекста. Категорически не подходит для многооборотного диалога с AI.
---
## Вариант 5: Бот создаёт приватные группы — ОТКЛОНЕНО
**Telegram Bot API не умеет создавать группы.** Единственный workaround — заранее создать 100+ пустых групп и назначать их пользователям. 1000 пользователей = 1000 лишних групп. Абсурд.
---
## Вариант 6: Telegram Web App (TWA) — Phase 2
### Суть
Кнопка в боте открывает мини-приложение (веб). Там красивый интерфейс со списком чатов, историей, поиском.
### Технические детали
```python
# В боте
from aiogram.types import WebAppInfo, InlineKeyboardButton
web_app_btn = InlineKeyboardButton(
text="📱 Открыть приложение",
web_app=WebAppInfo(url="https://lambda.example.com/app")
)
```
```javascript
// В TWA (JavaScript)
const tg = window.Telegram.WebApp;
const user_id = tg.initDataUnsafe.user.id;
// Загрузить список чатов
const chats = await fetch('/api/chats', {
headers: { 'X-Telegram-Init-Data': tg.initData }
}).then(r => r.json());
```
### Оценка
✅ Красивый интерфейс (история, поиск, форматирование)
✅ Мобильный-friendly
⚠️ Нужен HTTPS web-сервер
⚠️ Сложнее разрабатывать
⚠️ Усложняет деплой
**Вывод: хороший вариант для v2, не для MVP.**
---
## Финальные рекомендации
### Сейчас (MVP)
**Вариант 1 — Виртуальные чаты в DM.** Реализуется за 2-3 дня, нулевое friction, стандартный паттерн.
### Phase 2
**Вариант 6 — TWA** как дополнительный UI поверх той же логики. Бэкенд не меняется — просто добавляется web-интерфейс.
### Опционально (для пользователей которые хотят)
**Forum Topics** — оставить как opt-in возможность. Пользователь сам создаёт группу, добавляет бота — получает "продвинутый режим" с нативными Telegram темами.
---
## Что это означает для архитектуры
`ChatManager` в `core/chat.py` должен работать одинаково для обоих режимов — и виртуальных чатов в DM, и Forum Topics. Разница только в адаптере:
| | Telegram DM (virtual) | Telegram Forum | Matrix |
|-|-----------------------|----------------|--------|
| `chat_id` | UUID | `message_thread_id` | `room_id` |
| Создание | В БД | `create_forum_topic` | `room_create` |
| Отправка | `send_message(chat_id=user_id)` + tag | `send_message(thread_id=...)` | `room_send` |
| `core/` | Не знает разницы | Не знает разницы | Не знает разницы |