Architektura
Przegląd techniczny wewnętrznej budowy repartee.
Stos technologiczny
| Komponent | Technologia |
|---|---|
| Język | Rust, edycja 2024 |
| Framework TUI | ratatui 0.30.2 z backendem crossterm + ratatui-image 11.1.0 |
| Interfejs webowy | Leptos 0.7 (WASM CSR) + Axum 0.8 + rustls (aws_lc_rs) + beamterm-renderer 1.0 |
| Środowisko asynchroniczne | tokio (pełne funkcje) |
| Protokół IRC | crate irc-repartee v1.5.2 |
| Skryptowanie | Lua 5.4 przez mlua 0.12.2 |
| Przechowywanie | SQLite przez rusqlite 0.40.2 (wbudowany, WAL + FTS5) |
| Szyfrowanie | AES-256-GCM przez aes-gcm 0.11.1 (baza logów) + Ed25519 / X25519 / XChaCha20-Poly1305 (RPE2E v1) |
| Obsługa błędów | color-eyre + thiserror |
| Konfiguracja | TOML przez serde |
Architektura TEA
repartee stosuje wzorzec The Elm Architecture (TEA):
Model → Message → Update → View
- Model:
AppState-- cały stan aplikacji (bufory, połączenia, konfiguracja) - Message: Zdarzenia z IRC, klawiatury, myszy, timerów, sesji webowych, PTY powłoki
- Update: Handlery zdarzeń transformujące stan
- View: Funkcje renderowania ratatui odczytujące stan (oraz migawki rozsyłane do klientów webowych)
Stan jest niezależny od interfejsu -- moduł state/ nie importuje ratatui.
Struktura modułów
src/
main.rs # Entry point, fork, terminal setup, podkomendy CLI
app/ # Główna pętla zdarzeń, struktura App, dispatch zdarzeń
constants.rs # APP_NAME i stałe globalne
config/ # Ładowanie i walidacja konfiguracji TOML
state/ # Stan aplikacji (bufory, połączenia, sortowanie, typing, act)
session/ # Infrastruktura odłączania/podłączania
mod.rs # Ścieżki gniazd, listowanie sesji, żywotność PID
protocol.rs # Typy wiadomości Shim ↔ backend (ramkowanie bincode)
shim.rs # Shim terminala (pętla przekaźnikowa, splash, wejście)
writer.rs # SocketWriter (impl Write dla wyjścia gniazda)
irc/ # Połączenie IRC, obsługa zdarzeń, formatowanie
events.rs # Wiadomość IRC → aktualizacja stanu
mod.rs # Konfiguracja połączenia, negocjacja CAP, SASL, sonda bouncera
cap.rs # Framework IRCv3 CAP (ponad 30 możliwości)
isupport.rs # Parsowanie ISUPPORT + draft/extended-isupport
batch.rs # IRCv3 BATCH (netsplit/netjoin, chathistory, multiline, search)
sasl.rs # SASL PLAIN, EXTERNAL, SCRAM-SHA-1/256/512, ECDSA, OAUTHBEARER
extban.rs # Rozszerzone typy banów ($a:account itp.)
flood.rs # Ochrona przed floodem i limitowanie CTCP
netsplit.rs # Wykrywanie netsplitów
ignore.rs # Dopasowywanie listy ignorowanych
formatting.rs # Pomocniki formatowania IRC
whox.rs # Śledzenie WHOX (rozszerzone WHO)
dcc/ # Protokół DCC CHAT (aktywny i pasywny)
e2e/ # Szyfrowanie end-to-end RPE2E v1 (Ed25519, X25519, XChaCha20-Poly1305)
translate/ # Tłumaczenie wiadomości w locie (Lingva, Google, MyMemory, LibreTranslate)
shrink/ # Automatyczne skracanie URL (is.gd)
emote/ # Słownik i rozwijanie emotek tekstowych
image_preview/ # Podgląd obrazów w czacie i popupach (Kitty, iTerm2, Sixel, halfblocks)
shell/ # Wbudowane sesje terminala PTY (parser ekranu vt100)
spellcheck/ # Wielojęzyczne sprawdzanie pisowni Hunspell
web/ # Wbudowany serwer HTTPS/WebSocket, WebPush (RFC 8291), paczka WASM
ui/ # Renderowanie TUI
layout.rs # Układ ekranu + regiony
tree_list.rs # Drzewiasty i płaski pasek boczny buforów
nick_list.rs # Prawy pasek boczny
chat_view.rs # Wyświetlanie wiadomości + miniatury obrazów w czacie
bare_view.rs # Tryb bare (czysty widok do zaznaczania tekstu)
shell_view.rs # Widok wbudowanego terminala PTY
settings_modal.rs # Interaktywny modal /wizard i /config
window_overlay.rs # Przeszukiwalny popup /window list
input.rs # Wejście poleceń + autouzupełnianie Tab + ochrona wklejania
status_line.rs # Dolny pasek statusu (+typing, [E2E], [TR], [LAG], Act)
topic_bar.rs # Górny pasek tematu
message_line.rs # Renderowanie pojedynczej wiadomości
styled_text.rs # Ciągi formatujące → spany ratatui
theme/ # Ładowanie motywów + parser ciągów formatujących irssi
scripting/ # Silnik skryptowy Lua
engine.rs # Trait ScriptEngine + ScriptManager
api.rs # Nazwy zdarzeń i wiązania API Lua
event_bus.rs # Dispatch zdarzeń według priorytetu
lua/ # Backend Lua 5.4 (mlua 0.12.2)
storage/ # Logowanie SQLite + tabele pęku kluczy E2E
db.rs # Schemat bazy danych + migracje
writer.rs # Wsadowy zapis asynchroniczny
query.rs # Zapytania wyszukiwania i odczytu
crypto.rs # Szyfrowanie AES-256-GCM
types.rs # LogRow, StoredMessage
commands/ # System poleceń
parser.rs # Parsowanie argumentów /poleceń
registry.rs # Rejestracja poleceń (ponad 80 wbudowanych poleceń)
handlers_irc.rs # Polecenia IRC i IRCv3 (/join, /chathistory, /bouncer, /redact itp.)
handlers_ui.rs # Polecenia UI (/clear, /close, /wizard, /bare, /shell itp.)
handlers_admin.rs # Polecenia admina (/set, /reload, /e2e, /translate, /script itp.)
handlers_dcc.rs # Polecenia DCC (/dcc chat, /dcc close itp.)
docs.rs # Dwujęzyczny loader dokumentacji poleceń (EN + PL)
Architektura sesji
Przy uruchomieniu repartee rozdziela się na dwa procesy:
repartee
├── Backend (child) # headless daemon — IRC, state, socket listener
│ └── Unix socket # ~/.repartee/sessions/{pid}.sock
└── Shim (parent) # terminal bridge — renders UI, forwards input
Backend uruchamia pętlę zdarzeń tokio, zarządza połączeniami IRC, stanem, skryptami i logowaniem. Nasłuchuje na gnieździe Unix połączeń od shimów.
Shim przechwytuje zdarzenia terminala (klawiatura, mysz, zmiana rozmiaru) i wysyła je do backendu jako warianty ShimMessage. Backend renderuje ramki ratatui i wysyła surowe dane terminala z powrotem jako MainMessage::Output. Komunikacja używa serializacji bincode z prefiksem długości.
Przy odłączeniu shim kończy pracę (powłoka odzyskuje wiersz poleceń). Backend kontynuuje działanie. Przy ponownym podłączeniu nowy shim łączy się z gniazdem. Shim wysyła migawkę TerminalEnv (wymiary, rozmiar czcionki, zmienne środowiskowe typu terminala), aby backend mógł dostosować się do nowego terminala.
Przy SIGHUP (niespodziewane zamknięcie terminala) backend automatycznie się odłącza zamiast się wywalać.
Przepływ zdarzeń
- Zdarzenia terminala (klawiatura, mysz) przybywają przez
event::pollcrossterm w wątkuspawn_blocking(lub przez gniazdo od shima) - Zdarzenia są wysyłane kanałem tokio mpsc do głównej pętli
- Zdarzenia IRC przybywają przez asynchroniczny czytnik crate
irc, konwertowane na warianty enumIrcEvent - Główna pętla w
App::run()przetwarza wszystkie zdarzenia sekwencyjnie, aktualizującAppState - Po każdej partii zdarzeń interfejs jest ponownie renderowany z bieżącego stanu
Warstwa połączeń IRC
Każde połączenie z serwerem uruchamia:
- Asynchroniczne zadanie czytnika, które odbiera wiadomości IRC i wysyła
IrcEventdo współdzielonego kanału mpsc - Wiadomości są wysyłane przez
Senderz crateircprzechowywany w stanie połączenia
Wszystkie połączenia współdzielą jeden kanał zdarzeń, ze zdarzeniami oznaczonymi connection_id.
Architektura skryptowania
ScriptManager
└── Vec<Box<dyn ScriptEngine>>
└── LuaEngine (mlua)
├── Per-script Lua environments (sandboxed)
├── Event handlers (priority-sorted, per-event)
└── Command handlers
Trait ScriptEngine pozwala na dodawanie nowych języków (Rhai itp.) poprzez implementację traita i rejestrację w ScriptManager.
Obsługa IRCv3 i bouncerów
repartee implementuje ponad 30 możliwości IRCv3 oraz rozszerzeń bouncerów negocjowanych podczas połączenia przez CAP LS 302 / REQ / ACK (oraz dynamiczne CAP NEW / CAP DEL):
| Możliwość | Opis |
|---|---|
multi-prefix | Wiele prefiksów trybów na nick (np. @+nick) |
extended-join | Nazwa konta i realname w wiadomościach JOIN |
server-time | Znaczniki czasu wiadomości z serwera |
account-tag | Nazwa konta przy każdej wiadomości |
cap-notify | Powiadomienia o zmianach możliwości po stronie serwera |
away-notify | Zmiany statusu away w czasie rzeczywistym |
account-notify | Powiadomienia o logowaniu/wylogowaniu konta |
chghost | Zmiany ident/hostname w czasie rzeczywistym |
setname | Zmiany realname/gecos w czasie rzeczywistym (/setname) |
echo-message | Autorytatywne echo wysłanych wiadomości |
invite-notify | Powiadomienia o zaproszeniach na kanał |
batch | Grupowane partie wiadomości (netsplit, netjoin, chathistory, draft/multiline, soju.im/search) |
labeled-response | Korelacja żądanie/odpowiedź przez tagi @label |
userhost-in-names | Pełne user@host w odpowiedziach NAMES |
no-implicit-names | Pomijanie automatycznego zrzutu NAMES przy JOIN |
message-tags | Dowolne metadane wiadomości IRCv3 (+typing, +draft/reply, +draft/react, +draft/channel-context) |
monitor / extended-monitor | Serwerowe śledzenie obecności użytkowników (/monitor) |
draft/chathistory | Pobieranie historii wiadomości z serwera (/chathistory) |
draft/event-playback | Dołączanie zdarzeń w partiach historii |
draft/multiline | Przesyłanie i składanie wiadomości wieloliniowych |
draft/read-marker | Synchronizacja pozycji odczytu między urządzeniami (MARKREAD) |
draft/message-redaction | Serwerowe usuwanie wiadomości (REDACT / /redact) |
draft/account-registration | Rejestracja kont bezpośrednio przez połączenie (REGISTER / /register) |
draft/metadata-2 | Metadane klucz-wartość użytkowników i kanałów (METADATA / /metadata) |
draft/extended-isupport | Rozszerzone odkrywanie tokenów RPL_ISUPPORT przez komendę ISUPPORT |
draft/webpush | Natywne powiadomienia IRCv3 WebPush |
soju.im/bouncer-networks | Odkrywanie sieci bouncera i automatyczne tworzenie połączeń potomnych (BOUNCER) |
soju.im/bouncer-networks-notify | Powiadomienia na żywo o zmianach sieci bouncera |
soju.im/search | Serwerowe pełnotekstowe wyszukiwanie logów (SEARCH / /bsearch) |
soju.im/client-cert | Zarządzanie odciskami certyfikatów TLS klienta (CERTFP / /bcertfp) |
Obsługiwane mechanizmy SASL (wybór od najsilniejszego): ECDSA-NIST256P-CHALLENGE, SCRAM-SHA-512, SCRAM-SHA-256, SCRAM-SHA-1, EXTERNAL (certyfikat TLS klienta), OAUTHBEARER oraz PLAIN.
WHOX (rozszerzony WHO) jest automatycznie wykrywany i używany do wypełniania nazw kont oraz pełnych user@host dla wpisów nicków.
Potok przechowywania
AppState::add_message()
→ log_tx (tokio mpsc sender)
→ WriterTask (batches 50 rows / 1 second)
→ SQLite (WAL mode, FTS5 index)
Wiadomości przepływają z wątku interfejsu do zadania zapisu asynchronicznie, zapewniając zerowe blokowanie interfejsu na operacjach dyskowych.