Architektura

Przegląd techniczny wewnętrznej budowy repartee.

Stos technologiczny

KomponentTechnologia
JęzykRust, edycja 2024
Framework TUIratatui 0.30.2 z backendem crossterm + ratatui-image 11.1.0
Interfejs webowyLeptos 0.7 (WASM CSR) + Axum 0.8 + rustls (aws_lc_rs) + beamterm-renderer 1.0
Środowisko asynchronicznetokio (pełne funkcje)
Protokół IRCcrate irc-repartee v1.5.2
SkryptowanieLua 5.4 przez mlua 0.12.2
PrzechowywanieSQLite przez rusqlite 0.40.2 (wbudowany, WAL + FTS5)
SzyfrowanieAES-256-GCM przez aes-gcm 0.11.1 (baza logów) + Ed25519 / X25519 / XChaCha20-Poly1305 (RPE2E v1)
Obsługa błędówcolor-eyre + thiserror
KonfiguracjaTOML 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ń

  1. Zdarzenia terminala (klawiatura, mysz) przybywają przez event::poll crossterm w wątku spawn_blocking (lub przez gniazdo od shima)
  2. Zdarzenia są wysyłane kanałem tokio mpsc do głównej pętli
  3. Zdarzenia IRC przybywają przez asynchroniczny czytnik crate irc, konwertowane na warianty enum IrcEvent
  4. Główna pętla w App::run() przetwarza wszystkie zdarzenia sekwencyjnie, aktualizując AppState
  5. 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 IrcEvent do współdzielonego kanału mpsc
  • Wiadomości są wysyłane przez Sender z crate irc przechowywany 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-prefixWiele prefiksów trybów na nick (np. @+nick)
extended-joinNazwa konta i realname w wiadomościach JOIN
server-timeZnaczniki czasu wiadomości z serwera
account-tagNazwa konta przy każdej wiadomości
cap-notifyPowiadomienia o zmianach możliwości po stronie serwera
away-notifyZmiany statusu away w czasie rzeczywistym
account-notifyPowiadomienia o logowaniu/wylogowaniu konta
chghostZmiany ident/hostname w czasie rzeczywistym
setnameZmiany realname/gecos w czasie rzeczywistym (/setname)
echo-messageAutorytatywne echo wysłanych wiadomości
invite-notifyPowiadomienia o zaproszeniach na kanał
batchGrupowane partie wiadomości (netsplit, netjoin, chathistory, draft/multiline, soju.im/search)
labeled-responseKorelacja żądanie/odpowiedź przez tagi @label
userhost-in-namesPełne user@host w odpowiedziach NAMES
no-implicit-namesPomijanie automatycznego zrzutu NAMES przy JOIN
message-tagsDowolne metadane wiadomości IRCv3 (+typing, +draft/reply, +draft/react, +draft/channel-context)
monitor / extended-monitorSerwerowe śledzenie obecności użytkowników (/monitor)
draft/chathistoryPobieranie historii wiadomości z serwera (/chathistory)
draft/event-playbackDołączanie zdarzeń w partiach historii
draft/multilinePrzesyłanie i składanie wiadomości wieloliniowych
draft/read-markerSynchronizacja pozycji odczytu między urządzeniami (MARKREAD)
draft/message-redactionSerwerowe usuwanie wiadomości (REDACT / /redact)
draft/account-registrationRejestracja kont bezpośrednio przez połączenie (REGISTER / /register)
draft/metadata-2Metadane klucz-wartość użytkowników i kanałów (METADATA / /metadata)
draft/extended-isupportRozszerzone odkrywanie tokenów RPL_ISUPPORT przez komendę ISUPPORT
draft/webpushNatywne powiadomienia IRCv3 WebPush
soju.im/bouncer-networksOdkrywanie sieci bouncera i automatyczne tworzenie połączeń potomnych (BOUNCER)
soju.im/bouncer-networks-notifyPowiadomienia na żywo o zmianach sieci bouncera
soju.im/searchSerwerowe pełnotekstowe wyszukiwanie logów (SEARCH / /bsearch)
soju.im/client-certZarzą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.