nirc-rs/CHANGES.md

12 KiB

nirc-rs — Patch Summary

This file summarizes the patch batches applied to nirc-rs, newest first.


0.10.2 — BitChat Module Withdrawn

Date: 2026-07-29

The BitChat protocol module and all of its integrations have been removed from the codebase. See NOTICES.md for the full rationale.

Why

The BitChat project (Jack Dorsey's recently-announced P2P messaging protocol) is the subject of active litigation in the Indian courts. The legal status of the protocol specification, the reference implementation, and downstream reimplementations is currently unclear. Pending clarity, we have removed the module entirely rather than ship an encumbered protocol backend.

Files Changed

  • Deleted: src/protocols/bitchat.rs
  • src/protocols/mod.rs — removed pub mod bitchat; and re-exports
  • src/core/protocol.rs — removed ProtocolType::BitChat variant and all of its match arms in tag(), label(), badge(), naim_color(); updated the four protocol unit tests
  • src/core/command.rs — removed BitChatPeers, BitChatDm, BitChatSendFile command variants; removed the "bitchat" | "p2p" parser arm and the "bitchat" => ProtocolType::BitChat FromStr arm; removed the "bitchat" | "bc" | "p2p" arm from /xfer protocol lookup
  • src/engine/dispatcher.rs — removed ProtocolCommand::BitChat variant; removed connect_bitchat() method; removed BitChat dispatch arms in Msg, Me, Say, quit_for, and the explicit BitChatPeers/BitChatDm/BitChatSendFile handler block; removed BitChat from the connect dispatch and the tag-map lookup table
  • src/tui/menubar.rs — removed the "Connect → BitChat…" menu entry
  • src/tui/chat_view.rs — removed BitChat from the protocol color lookup tables (both dim-color and NaimColor)
  • src/tui/winlist.rs — removed BitChat from the badge char and badge color lookup tables; updated the module-level doc
  • src/core/history.rs — removed the "P2P" => BitChat tag mapping (old history files with this tag will be silently reassigned to Status)
  • src/logging/mod.rs — removed BitChat from sanitize_server match; updated the test
  • src/transfer/engine.rs — updated the integration test to use ProtocolType::Adc instead of ProtocolType::BitChat
  • src/core/app.rs — updated the next_tab_by_priority_mixes_protocols_freely test to use ProtocolType::Adc instead of ProtocolType::BitChat
  • src/config/mod.rs — updated the BitChat server-entries doc section to note the removal
  • src/engine/crypto.rs — updated the module-level doc to note that the Noise primitive is now only used by ADC (was previously shared with BitChat)
  • src/main.rs — renamed _p2p_keypair_noise_keypair (still generated, since ADC uses it); removed the BitChat help text and replaced with a media-commands help section + a BitChat-removed note; removed the Command::BitChatPeers | BitChatDm | BitChatSendFile dispatch arm
  • Cargo.toml — bumped version to 0.10.2; removed libp2p dependency (BitChat was the only consumer); removed "p2p" from the keywords list
  • NOTICES.md — new file, contains the full rationale and re-evaluation criteria for the BitChat withdrawal
  • README.md, STATUS.md, TODO.md, QUICKSTART.md/quickstart.md, man/man1/nirc.1, completions/nirc.{bash,zsh,fish}, packaging/PKGBUILD, packaging/nirc.spec, packaging/debian/DEBIAN/control, BLOG_POST.md — updated to reflect the removal and point at NOTICES.md

User Impact

  • Existing configs: Any [[servers]] entry with protocol = "bitchat" will be silently ignored at load time. You do not need to edit your config file, but you may remove the entries to clean it up.
  • Existing history files: Per-tab scrollback files tagged P2P:<name> will fail to match any known protocol on load and will be silently assigned to the Status tab. The files themselves are not deleted; you can read them with a text editor if you need to recover the content.
  • No data loss: Your IRC / Matrix / ADC / Discord / Stout / Spacebar / Nerimity history, configs, and credentials are unaffected.

Re-evaluation Criteria

We will re-evaluate restoring the BitChat module when all of the following are true:

  1. The India courts case has reached a final judgement (not an interim order), OR the parties have publicly settled and the settlement terms are clear about downstream-implementation rights.
  2. The BitChat reference implementation's license is unambiguous and permits third-party reimplementations.
  3. There is at least one independent legal opinion (not from a party to the litigation) concluding that shipping a clean-room reimplementation of the protocol is safe.

Until then, the module will remain withdrawn.


0.10.1 — IRC Fixes, Throttle, Rotation Revert, URLs/Media, Bandwidth Monitor, Line Wrap

Date: 2026-07-28

This patch batch addresses the user-reported issues with nirc-rs 0.10.0 and adds several requested features. The changes are organized into five phases.

Phase 1: IRC Protocol Fixes (src/protocols/irc.rs, src/main.rs)

  • CTCP spec compliance — Outgoing CTCP requests now use PRIVMSG (was NOTICE). Per the IRCv3 CTCP spec, requests must be PRIVMSG; only replies use NOTICE. This was why /ctcp <nick> VERSION was silently ignored by strict servers.
  • Self-targeted CTCP visible/ctcp mynick VERSION now displays the request in the relevant tab. Previously the entire CTCP block was skipped when the sender was the local nick, silently swallowing self-targeted queries.
  • /away tracking — Added is_away and away_message fields to ConnState. The /away [msg] command optimistically marks the local state and posts a confirmation notice. Added explicit handlers for RPL_NOWAWAY (306) and RPL_UNAWAY (305) instead of letting them fall through to the generic numeric dump.
  • IRCv3 away-notify handler — Added a dedicated AWAY command handler that caches the away reason per nick in state.nick_away and posts a notice. Previously the away-notify capability was negotiated but the incoming AWAY messages fell into the "Unhandled command" path.
  • /who hardeningRPL_WHOREPLY (352) now correctly splits the trailing field into hopcount and realname (per RFC 1459), displays the here/away flag (H/G) from the flags field, marks self-entries with (you), and has an explicit RPL_ENDOFWHO (315) terminator handler. This addresses the historical /who <self> crash.
  • /me local echo (src/main.rs) — Actions are now echoed locally in the active tab immediately, so the user sees their action even on servers that don't echo own PRIVMSGs (bouncers, mock servers, etc.).
  • /notice local echo (src/main.rs) — Same local-echo treatment for sent notices.

Phase 2: Input Rate Throttle + Channel Rotation Revert

  • New module: src/core/throttle.rsInputThrottle struct with sliding-window rate limiting and per-send line cap. Returns Allow { lines_sent } or Reject { lines_sent, dropped, reason }. 7 unit tests.
  • src/main.rs — Wired the throttle into the SendMessage path. Input is split on newlines (paste guard), capped at 4 lines per submission, and rate-limited to 8 lines per 3 seconds. Rejected lines produce a single warning notice per burst (subsequent rejections are silent to avoid flooding the user's tab).
  • src/core/app.rs — Reverted next_tab_by_priority and prev_tab_by_priority to static insertion-order cycling. The previous activity-tier-based reordering made Ctrl-N feel non-deterministic. Updated 4 existing tests to reflect the new behaviour.

Phase 3: URL Detection + Inline Photo + External Video

  • New module: src/tui/media.rs — URL detection (detect_urls), media classification (classify_url: image/video/other by extension), external launching (open_external: xdg-open / open / start with http-scheme safety check), inline-image protocol detection (detect_image_protocol: Kitty / iTerm2 / Sixel / None), and a try_render_inline_image stub that gracefully returns Unsupported for now. 20+ unit tests.
  • src/tui/chat_view.rsrender_body now scans each text segment for URLs and renders them underlined in cyan. This is the foundation for the inline-photo and external-video features.
  • src/core/command.rs — Added Command::Url, Command::Video, Command::Image variants and parsers (/url, /video, /image commands).
  • src/main.rs — Added handlers for the new commands in handle_user_command. /image attempts inline rendering and falls back to external open if the terminal doesn't support it.

Phase 4: Top-Right Bandwidth Monitor

  • src/transfer/mod.rs — Added TransferSummary struct and TransferManager::summary() method. The summary samples each active transfer's bytes_transferred against the previous frame's sample to compute instantaneous bytes/sec. Tracks the top transfer by bandwidth (most active file). Rate-sampling state is cleaned up when transfers complete.
  • src/tui/input_bar.rsrender_top_status_bar_naim and render_top_status_bar now accept an Option<&TransferSummary> parameter. When transfers are active, the static nirc label in the top-right is replaced with ↓rate ↑rate filename %. Falls back to nirc when no transfers are active.
  • src/main.rs — Calls transfer_manager.summary() once per frame and passes the result to the top status bar renderer.

Phase 5: Line Wrapping Fix

  • src/tui/chat_view.rs — Added wrap_text(text, max_cols) helper that breaks on word boundaries when possible and falls back to hard character breaks for words longer than the available width (e.g. long URLs). The ChatView::render method now wraps each body line to fit the available width instead of truncating at the right margin. 5 unit tests.

New Commands

  • /url <url> — open a URL in the OS default browser (xdg-open / open / start)
  • /video <url> — launch a video URL in the OS default video player
  • /image <url> — attempt inline image rendering; falls back to /url if the terminal doesn't support inline images

Configuration

The throttle limits are currently hardcoded in src/core/throttle.rs:

  • MAX_LINES_PER_SEND = 4 — max lines per single input submission
  • MAX_LINES_PER_WINDOW = 8 — max lines per sliding window
  • WINDOW_SECS = 3 — sliding window duration in seconds

These will be exposed as config options in a future release (see TODO.md).


What's NOT in These Patches (Deferred)

Per user direction, the following are deferred to follow-up sessions:

  • Matrix protocol production hardening — Most complex of the group, gets its own session.
  • Stout / Spacebar / Nerimity full builds — These are currently true stubs whose run_*() functions just log placeholder notices. Building them out to "production ready" is multiple full protocol implementations, each comparable in scope to the Discord backend.
  • Real inline image rendering — The try_render_inline_image() function is a stub returning Unsupported. The graceful-fallback path (text placeholder + external open) is wired up, so this is a pure feature add with no risk to existing functionality. See TODO.md for the implementation outline.
  • Configurable throttle limits — Currently hardcoded; will be exposed via config.toml in a future release.