535 lines
18 KiB
Markdown
535 lines
18 KiB
Markdown
|
|
# Montana Communications — Техническая Спецификация
|
|||
|
|
|
|||
|
|
**Версия:** 1.0
|
|||
|
|
**Дата:** 2026-01-21
|
|||
|
|
**Автор:** Alejandro Montana
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Обзор
|
|||
|
|
|
|||
|
|
Montana Communications — единая система коммуникаций протокола Montana, где **время = деньги** в буквальном смысле. Каждая секунда голосового или видеозвонка стоит 1 Jcoin.
|
|||
|
|
|
|||
|
|
**Принцип:** Телефон — это адрес кошелька. SMS — это транзакция. Звонок — это стриминг времени.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Архитектура
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|||
|
|
│ MONTANA COMMUNICATIONS │
|
|||
|
|
├─────────────────────────────────────────────────────────────────────┤
|
|||
|
|
│ │
|
|||
|
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|||
|
|
│ │ SMS │ │ VOICE │ │ VIDEO │ │
|
|||
|
|
│ │ Gateway │ │ WebRTC │ │ WebRTC │ │
|
|||
|
|
│ │ │ │ │ │ │ │
|
|||
|
|
│ │ 1 SMS = 1Ɉ │ │ 1 sec = 1Ɉ │ │ 1 sec = 2Ɉ │ │
|
|||
|
|
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
|||
|
|
│ │ │ │ │
|
|||
|
|
│ └──────────────────┼──────────────────┘ │
|
|||
|
|
│ │ │
|
|||
|
|
│ ▼ │
|
|||
|
|
│ ┌─────────────────┐ │
|
|||
|
|
│ │ SIGNALING │ │
|
|||
|
|
│ │ (Telegram Bot) │ │
|
|||
|
|
│ └────────┬────────┘ │
|
|||
|
|
│ │ │
|
|||
|
|
│ ▼ │
|
|||
|
|
│ ┌─────────────────┐ │
|
|||
|
|
│ │ BILLING │ │
|
|||
|
|
│ │ (Time = Money) │ │
|
|||
|
|
│ └────────┬────────┘ │
|
|||
|
|
│ │ │
|
|||
|
|
│ ▼ │
|
|||
|
|
│ ┌─────────────────┐ │
|
|||
|
|
│ │ MONTANA DB │ │
|
|||
|
|
│ │ (SQLite) │ │
|
|||
|
|
│ └─────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
└─────────────────────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. SMS Gateway
|
|||
|
|
|
|||
|
|
### Концепция
|
|||
|
|
|
|||
|
|
**Телефон = Адрес кошелька.** Любой человек в мире может отправить SMS и получить кошелёк Montana без регистрации.
|
|||
|
|
|
|||
|
|
### Формат адреса
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
+79991234567 → Международный (E.164)
|
|||
|
|
телефон = wallet address
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Команды SMS
|
|||
|
|
|
|||
|
|
| Команда | Описание | Пример |
|
|||
|
|
|---------|----------|--------|
|
|||
|
|
| `BAL` | Проверить баланс | `BAL` |
|
|||
|
|
| `SEND <тел> <сумма>` | Перевод | `SEND +79991234567 100` |
|
|||
|
|
| `TX` | История транзакций | `TX` |
|
|||
|
|
| `INFO` | Информация об аккаунте | `INFO` |
|
|||
|
|
| `?` | Справка | `?` |
|
|||
|
|
|
|||
|
|
### Архитектура SMS
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|||
|
|
│ Телефон │──SMS─│ Twilio │─HTTP─│ Montana │
|
|||
|
|
│ (+7...) │ │ Webhook │ │ Gateway │
|
|||
|
|
└─────────────┘ └─────────────┘ └──────┬──────┘
|
|||
|
|
│
|
|||
|
|
┌──────────────────────┤
|
|||
|
|
│ │
|
|||
|
|
▼ ▼
|
|||
|
|
┌─────────────┐ ┌─────────────┐
|
|||
|
|
│ Montana │ │ Telegram │
|
|||
|
|
│ DB │ │ Bot │
|
|||
|
|
└─────────────┘ └─────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Синхронизация Telegram ↔ SMS
|
|||
|
|
|
|||
|
|
Если пользователь привязал телефон к Telegram аккаунту Montana:
|
|||
|
|
- Баланс синхронизирован
|
|||
|
|
- Транзакции видны в обоих каналах
|
|||
|
|
- Можно звонить через любой интерфейс
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
def link_phone_to_telegram(phone: str, telegram_id: str) -> bool:
|
|||
|
|
"""
|
|||
|
|
Привязка телефона к Telegram.
|
|||
|
|
Балансы объединяются.
|
|||
|
|
"""
|
|||
|
|
phone_balance = get_balance(phone)
|
|||
|
|
tg_balance = get_balance(f"tg:{telegram_id}")
|
|||
|
|
|
|||
|
|
# Объединяем балансы
|
|||
|
|
total = phone_balance + tg_balance
|
|||
|
|
|
|||
|
|
# Устанавливаем единый баланс
|
|||
|
|
set_balance(phone, total)
|
|||
|
|
set_balance(f"tg:{telegram_id}", total)
|
|||
|
|
|
|||
|
|
# Создаём связь
|
|||
|
|
create_link(phone, telegram_id)
|
|||
|
|
return True
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Тарификация SMS
|
|||
|
|
|
|||
|
|
| Операция | Стоимость |
|
|||
|
|
|----------|-----------|
|
|||
|
|
| Входящее SMS (команда) | 1 Ɉ |
|
|||
|
|
| Исходящее SMS (ответ) | 0 Ɉ (включено) |
|
|||
|
|
| Перевод (SEND) | 1 Ɉ + комиссия 1% |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Voice (WebRTC P2P)
|
|||
|
|
|
|||
|
|
### Концепция
|
|||
|
|
|
|||
|
|
Голосовые звонки через WebRTC — P2P соединение между устройствами. Montana только обеспечивает signaling и биллинг.
|
|||
|
|
|
|||
|
|
**Принцип:** Голос идёт напрямую между устройствами. Montana не слышит разговор.
|
|||
|
|
|
|||
|
|
### Архитектура WebRTC
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────┐ ┌─────────────┐
|
|||
|
|
│ Телефон A │ │ Телефон B │
|
|||
|
|
│ (Browser) │ │ (Browser) │
|
|||
|
|
└──────┬──────┘ └──────┬──────┘
|
|||
|
|
│ │
|
|||
|
|
│ 1. Offer (SDP) │
|
|||
|
|
├──────────────────► Signaling ◄────────────┤
|
|||
|
|
│ (Telegram) │
|
|||
|
|
│ 2. Answer (SDP) │
|
|||
|
|
├◄───────────────────────────────────────────┤
|
|||
|
|
│ │
|
|||
|
|
│ 3. ICE Candidates │
|
|||
|
|
├◄──────────────────────────────────────────►│
|
|||
|
|
│ │
|
|||
|
|
│ 4. P2P Media Stream (Encrypted) │
|
|||
|
|
└◄══════════════════════════════════════════►┘
|
|||
|
|
│
|
|||
|
|
1 секунда = 1 Ɉ
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### ICE серверы
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
ICE_SERVERS = [
|
|||
|
|
# STUN серверы (NAT traversal)
|
|||
|
|
{"urls": "stun:stun.l.google.com:19302"},
|
|||
|
|
{"urls": "stun:stun1.l.google.com:19302"},
|
|||
|
|
{"urls": "stun:stun2.l.google.com:19302"},
|
|||
|
|
{"urls": "stun:stun3.l.google.com:19302"},
|
|||
|
|
{"urls": "stun:stun4.l.google.com:19302"},
|
|||
|
|
|
|||
|
|
# TURN сервер (для symmetric NAT) — опционально
|
|||
|
|
# {"urls": "turn:turn.efir.org:3478",
|
|||
|
|
# "username": "montana",
|
|||
|
|
# "credential": "<from_keychain>"}
|
|||
|
|
]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Signaling через Telegram
|
|||
|
|
|
|||
|
|
Вместо отдельного WebSocket сервера используем Telegram бот как signaling:
|
|||
|
|
|
|||
|
|
1. **Caller** создаёт offer (SDP) в браузере
|
|||
|
|
2. **Offer** передаётся через Telegram бот получателю
|
|||
|
|
3. **Receiver** создаёт answer (SDP)
|
|||
|
|
4. **Answer** передаётся обратно через бот
|
|||
|
|
5. **ICE candidates** обмениваются через бот
|
|||
|
|
6. **P2P соединение** установлено — голос идёт напрямую
|
|||
|
|
|
|||
|
|
### WebRTC клиент
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// Создание peer connection
|
|||
|
|
const pc = new RTCPeerConnection({iceServers: ICE_SERVERS});
|
|||
|
|
|
|||
|
|
// Получить доступ к микрофону
|
|||
|
|
const stream = await navigator.mediaDevices.getUserMedia({audio: true});
|
|||
|
|
stream.getTracks().forEach(track => pc.addTrack(track, stream));
|
|||
|
|
|
|||
|
|
// Создать offer
|
|||
|
|
const offer = await pc.createOffer();
|
|||
|
|
await pc.setLocalDescription(offer);
|
|||
|
|
|
|||
|
|
// Отправить offer через Telegram (signaling)
|
|||
|
|
sendToTelegram({type: 'offer', sdp: offer.sdp});
|
|||
|
|
|
|||
|
|
// Получить answer от второй стороны
|
|||
|
|
pc.ontrack = (e) => {
|
|||
|
|
// Воспроизвести входящий аудиопоток
|
|||
|
|
audioElement.srcObject = e.streams[0];
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Биллинг звонков
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
def end_call(call_id: str) -> dict:
|
|||
|
|
"""
|
|||
|
|
Завершение звонка и списание Ɉ
|
|||
|
|
"""
|
|||
|
|
call = get_call(call_id)
|
|||
|
|
|
|||
|
|
# Расчёт времени
|
|||
|
|
duration = (call.ended_at - call.started_at).total_seconds()
|
|||
|
|
duration_seconds = int(duration)
|
|||
|
|
|
|||
|
|
# 1 секунда = 1 Ɉ
|
|||
|
|
cost = duration_seconds
|
|||
|
|
|
|||
|
|
# Списание со звонящего
|
|||
|
|
transfer(
|
|||
|
|
from_address=call.from_address,
|
|||
|
|
to_address="BURN", # или пул узлов
|
|||
|
|
amount=cost,
|
|||
|
|
memo=f"Call {call_id}: {duration_seconds}s"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
"call_id": call_id,
|
|||
|
|
"duration_seconds": duration_seconds,
|
|||
|
|
"cost_coins": cost
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Команды Telegram
|
|||
|
|
|
|||
|
|
| Команда | Описание |
|
|||
|
|
|---------|----------|
|
|||
|
|
| `/call @user` | Позвонить пользователю |
|
|||
|
|
| `/call +79991234567` | Позвонить на телефон |
|
|||
|
|
| `/answer` | Принять входящий звонок |
|
|||
|
|
| `/hangup` | Завершить звонок |
|
|||
|
|
| `/calls` | История звонков |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Video (WebRTC P2P)
|
|||
|
|
|
|||
|
|
### Концепция
|
|||
|
|
|
|||
|
|
Видеозвонки используют ту же архитектуру WebRTC, но с видеопотоком.
|
|||
|
|
|
|||
|
|
**Тариф:** 1 секунда = 2 Ɉ (audio + video)
|
|||
|
|
|
|||
|
|
### Отличия от Voice
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// Видеозвонок — включаем камеру
|
|||
|
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|||
|
|
audio: true,
|
|||
|
|
video: {
|
|||
|
|
width: { ideal: 1280 },
|
|||
|
|
height: { ideal: 720 },
|
|||
|
|
facingMode: "user"
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Тарификация видео
|
|||
|
|
|
|||
|
|
| Тип | Стоимость |
|
|||
|
|
|-----|-----------|
|
|||
|
|
| Voice call | 1 Ɉ/сек |
|
|||
|
|
| Video call | 2 Ɉ/сек |
|
|||
|
|
| Screen share | 2 Ɉ/сек |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## База данных
|
|||
|
|
|
|||
|
|
### Таблица calls
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE IF NOT EXISTS calls (
|
|||
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|||
|
|
call_id TEXT UNIQUE NOT NULL,
|
|||
|
|
from_address TEXT NOT NULL,
|
|||
|
|
to_address TEXT NOT NULL,
|
|||
|
|
started_at TEXT,
|
|||
|
|
ended_at TEXT,
|
|||
|
|
duration_seconds INTEGER DEFAULT 0,
|
|||
|
|
cost_coins INTEGER DEFAULT 0,
|
|||
|
|
status TEXT DEFAULT 'pending',
|
|||
|
|
call_type TEXT DEFAULT 'voice', -- voice/video/screen
|
|||
|
|
offer_sdp TEXT,
|
|||
|
|
answer_sdp TEXT,
|
|||
|
|
ice_candidates_from TEXT, -- JSON array
|
|||
|
|
ice_candidates_to TEXT, -- JSON array
|
|||
|
|
created_at TEXT NOT NULL
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_calls_from ON calls(from_address);
|
|||
|
|
CREATE INDEX idx_calls_to ON calls(to_address);
|
|||
|
|
CREATE INDEX idx_calls_status ON calls(status);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Статусы звонка
|
|||
|
|
|
|||
|
|
| Статус | Описание |
|
|||
|
|
|--------|----------|
|
|||
|
|
| `pending` | Звонок инициирован, ждёт ответа |
|
|||
|
|
| `ringing` | Получатель видит входящий звонок |
|
|||
|
|
| `active` | Разговор в процессе |
|
|||
|
|
| `ended` | Завершён нормально |
|
|||
|
|
| `missed` | Пропущен |
|
|||
|
|
| `rejected` | Отклонён |
|
|||
|
|
| `failed` | Ошибка соединения |
|
|||
|
|
|
|||
|
|
### Таблица sms_transactions
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE IF NOT EXISTS sms_transactions (
|
|||
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|||
|
|
phone TEXT NOT NULL,
|
|||
|
|
direction TEXT NOT NULL, -- inbound/outbound
|
|||
|
|
message TEXT,
|
|||
|
|
command TEXT,
|
|||
|
|
result TEXT,
|
|||
|
|
cost_coins INTEGER DEFAULT 1,
|
|||
|
|
created_at TEXT NOT NULL
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Безопасность
|
|||
|
|
|
|||
|
|
### Шифрование
|
|||
|
|
|
|||
|
|
| Компонент | Шифрование |
|
|||
|
|
|-----------|------------|
|
|||
|
|
| WebRTC Media | SRTP (AES-128) |
|
|||
|
|
| Signaling | Telegram TLS |
|
|||
|
|
| SDP | Транспортное шифрование |
|
|||
|
|
| ICE | DTLS |
|
|||
|
|
|
|||
|
|
### Приватность
|
|||
|
|
|
|||
|
|
- **P2P:** Голос/видео идут напрямую между устройствами
|
|||
|
|
- **Montana не слышит:** Сервер только signaling и биллинг
|
|||
|
|
- **Нет записи:** Montana не хранит медиа
|
|||
|
|
- **End-to-End:** SRTP шифрование между браузерами
|
|||
|
|
|
|||
|
|
### Защита от атак
|
|||
|
|
|
|||
|
|
| Атака | Защита |
|
|||
|
|
|-------|--------|
|
|||
|
|
| MITM | DTLS fingerprint verification |
|
|||
|
|
| DoS звонками | Минимальный баланс 60 Ɉ |
|
|||
|
|
| Spam SMS | Rate limiting + стоимость 1 Ɉ |
|
|||
|
|
| Fake caller ID | WebRTC peer verification |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## API
|
|||
|
|
|
|||
|
|
### CallManager
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from webrtc_signaling import CallManager
|
|||
|
|
|
|||
|
|
manager = CallManager()
|
|||
|
|
|
|||
|
|
# Инициировать звонок
|
|||
|
|
success, msg, call_id = manager.initiate_call(
|
|||
|
|
from_address="tg:123456789",
|
|||
|
|
to_address="tg:987654321"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# Установить SDP offer
|
|||
|
|
manager.set_offer(call_id, offer_sdp)
|
|||
|
|
|
|||
|
|
# Принять звонок
|
|||
|
|
manager.answer_call(call_id, answer_sdp)
|
|||
|
|
|
|||
|
|
# Добавить ICE candidate
|
|||
|
|
manager.add_ice_candidate(call_id, candidate, is_from=True)
|
|||
|
|
|
|||
|
|
# Начать тарификацию (P2P соединено)
|
|||
|
|
manager.start_call(call_id)
|
|||
|
|
|
|||
|
|
# Завершить и списать
|
|||
|
|
success, info = manager.end_call(call_id)
|
|||
|
|
# info = {"duration_seconds": 120, "cost_coins": 120}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### SMSGateway
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from sms_gateway import SMSGateway
|
|||
|
|
|
|||
|
|
gateway = SMSGateway()
|
|||
|
|
|
|||
|
|
# Обработать входящее SMS
|
|||
|
|
response = gateway.process_incoming(
|
|||
|
|
from_phone="+79991234567",
|
|||
|
|
body="BAL"
|
|||
|
|
)
|
|||
|
|
# response = "Баланс: 1000 Ɉ"
|
|||
|
|
|
|||
|
|
# Отправить SMS
|
|||
|
|
gateway.send_sms(
|
|||
|
|
to_phone="+79991234567",
|
|||
|
|
message="Перевод получен: 100 Ɉ"
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Интеграция с Telegram
|
|||
|
|
|
|||
|
|
### MiniApp для звонков
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
https://efir.org/call?id=CALL-XXXXXXXX
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
MiniApp открывается внутри Telegram и использует WebRTC для звонка.
|
|||
|
|
|
|||
|
|
### Webhook обработка
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
@dp.message(Command("call"))
|
|||
|
|
async def call_cmd(message: Message):
|
|||
|
|
"""Инициировать WebRTC звонок"""
|
|||
|
|
|
|||
|
|
target = extract_target(message.text)
|
|||
|
|
if not target:
|
|||
|
|
await message.answer("Использование: /call @user или /call +79991234567")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# Проверяем баланс (минимум 60 Ɉ = 1 минута)
|
|||
|
|
balance = db.get_balance(message.from_user.id)
|
|||
|
|
if balance < 60:
|
|||
|
|
await message.answer("Минимальный баланс для звонка: 60 Ɉ (1 минута)")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# Создаём звонок
|
|||
|
|
success, msg, call_id = call_manager.initiate_call(
|
|||
|
|
from_address=f"tg:{message.from_user.id}",
|
|||
|
|
to_address=target
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# Отправляем ссылку на WebRTC клиент
|
|||
|
|
await message.answer(
|
|||
|
|
f"Звонок: {call_id}\n\n"
|
|||
|
|
f"Откройте для звонка:\n"
|
|||
|
|
f"https://efir.org/call?id={call_id}"
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Тарификация
|
|||
|
|
|
|||
|
|
### Сводная таблица
|
|||
|
|
|
|||
|
|
| Услуга | Стоимость | Минимум |
|
|||
|
|
|--------|-----------|---------|
|
|||
|
|
| SMS команда | 1 Ɉ | 1 Ɉ |
|
|||
|
|
| Voice call | 1 Ɉ/сек | 60 Ɉ |
|
|||
|
|
| Video call | 2 Ɉ/сек | 120 Ɉ |
|
|||
|
|
| Перевод | 1% | 1 Ɉ |
|
|||
|
|
|
|||
|
|
### Экономика
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1 Ɉ = 1 секунда времени
|
|||
|
|
1 минута звонка = 60 Ɉ
|
|||
|
|
1 час звонка = 3600 Ɉ
|
|||
|
|
|
|||
|
|
TIME IS THE ONLY REAL CURRENCY
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Файлы модуля
|
|||
|
|
|
|||
|
|
| Файл | Назначение |
|
|||
|
|
|------|------------|
|
|||
|
|
| `sms_gateway.py` | SMS Gateway (Twilio webhook) |
|
|||
|
|
| `webrtc_signaling.py` | WebRTC signaling через Telegram |
|
|||
|
|
| `static/call.html` | WebRTC клиент (браузер) |
|
|||
|
|
| `montana_db.py` | База данных (таблица calls) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Roadmap
|
|||
|
|
|
|||
|
|
### v1.0 (текущая)
|
|||
|
|
- [x] SMS Gateway (BAL, SEND, TX)
|
|||
|
|
- [x] Voice calls (WebRTC P2P)
|
|||
|
|
- [x] Signaling через Telegram
|
|||
|
|
- [x] Биллинг по секундам
|
|||
|
|
|
|||
|
|
### v1.1 (планируется)
|
|||
|
|
- [ ] Video calls
|
|||
|
|
- [ ] Screen sharing
|
|||
|
|
- [ ] Telegram MiniApp
|
|||
|
|
- [ ] TURN сервер на Timeweb
|
|||
|
|
|
|||
|
|
### v2.0 (будущее)
|
|||
|
|
- [ ] Group calls (до 12 участников)
|
|||
|
|
- [ ] Voicemail (оплата за хранение)
|
|||
|
|
- [ ] Call recording (opt-in, оплата)
|
|||
|
|
- [ ] SIP интеграция
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**Montana Protocol — Time is the only real currency.**
|