neegde¶
neegde is a Tauri 2 desktop application for streaming music from two sources: RuTracker (BitTorrent-based) and SoulSeek (P2P). This wiki documents the internal implementation for anyone who wants to understand, audit, or contribute to the codebase.
The codebase lives at github.com/yepIwt/neegde-tauri.
Stack¶
| Layer | Technology |
|---|---|
| Desktop shell | Tauri 2 |
| Frontend | Vue 3 + TypeScript + Vite |
| Backend | Rust (tokio, reqwest, serde) |
| BitTorrent streaming | vozduxan — a custom C++ library wrapping libtorrent |
| BitTorrent export | librqbit (Rust) |
| SoulSeek | Custom Rust implementation of the SoulSeek binary protocol |
How it works, in one paragraph¶
The user types a query. The Rust resolver canonicalizes it — turning "нон стоп молли" into {artist: "Пошлая Молли", title: "Нон стоп"} — using Brave Search with an Argon2id proof-of-work challenge. The search engine feeds that canonical string to two providers in parallel: the RuTracker provider fetches HTML search results over an authenticated session, parses torrent topics, and extracts album/track structure; the SoulSeek provider sends a network-level search packet to the SoulSeek server and streams peer responses as they arrive. Results go through a pipeline (normalize → dedup → score → filter) and are rendered reactively. When the user plays a track, the RuTracker path calls into vozduxan (C++, libtorrent) which opens the torrent, priorities the requested file's pieces with deadline scheduling, starts a local HTTP server, and returns a localhost:… URL to the <audio> element. SoulSeek opens a direct TCP connection to the file's owner peer and does the same.
Repository layout¶
neegde-tauri/
├── src/ Vue 3 frontend (TypeScript)
│ ├── App.vue Application shell, main layout
│ ├── search/ Search engine, session, providers, pipeline
│ ├── stores/ Reactive state (queue, entities, search, likes)
│ ├── persistence/ localStorage serialization helpers
│ ├── torrent/ Tauri command wrappers for streaming
│ ├── soulseek/ SoulSeek frontend API wrappers
│ ├── rutracker/ RuTracker auth, search, session helpers
│ └── components/ Vue components (player, search, torrent view)
│
└── src-tauri/
├── build.rs CMake invocation for vozduxan
└── src/
├── lib.rs Tauri setup, managed state, invoke_handler
├── app_paths.rs Canonical data directory helpers
├── vozduxan_ffi.rs Raw unsafe C bindings
├── vozduxan_stream.rs Safe Rust wrapper, token buckets
├── resolver/ Query intent resolver
├── rutracker/ HTTP session, search, topic parsing
├── soulseek/ SoulSeek protocol implementation
├── torrent_stream/ Export + AppDebugLog (librqbit-based)
└── torrent_image.rs Cover art via transient librqbit sessions
Major subsystems¶
Streaming¶
All audio playback goes through one of two paths: vozduxan for RuTracker content, and a direct peer download for SoulSeek. Both expose the same interface to the frontend: a localhost URL ready for an <audio> element.
The vozduxan path uses three token buckets — current_token, prefetch_token, warm_prefetch_token — managed in Rust to avoid evicting the wrong cached stream when the user navigates the queue.
Query Resolver¶
User input is rarely clean. The resolver runs Brave Search restricted to genius.com, parses the returned page titles to extract artist and track name, and produces a ResolveResult with a canonical pair and an intent label (track, artist, album, lyric, raw). When Brave returns a 429 with a JSON challenge body, the resolver solves the Argon2id PoW locally and retries.
Search Pipeline¶
SearchEngine manages one SearchSession per unique query. A session runs two async generators (providers) in parallel, collects their snapshots in a Map<providerKind, PipelineEntity[]>, merges them on every animation frame, and pushes the result through the pipeline. The pipeline currently does deduplication (by entity id, merging source lists) and filtering; scoring is a placeholder.
RuTracker¶
Auth uses a real phpBB session: a POST to the login endpoint with Windows-1251 encoded credentials, cookies persisted via reqwest_cookie_store. Search parses the topic listing HTML, then fetches the full post body for each topic to extract magnet link, file list, cover image, and structured metadata (year, codec, rip type, genre).
SoulSeek¶
A Rust implementation of the SoulSeek binary protocol: TCP connection to the SoulSeek server, login handshake, and file search via a length-prefixed binary packet. Peer responses arrive incrementally. Streaming is a direct HTTP download from the peer (or from an alternative peer if the primary fails). Up to five fallback peers are stored per track.
Key invariants¶
These are the non-obvious constraints that will break things silently if violated:
-
VozduxanStreamState,TorrentImageState, andTorrentStreamStatemust share the sameArc<AppDebugLog>. They are constructed inlib.rsand the Arc is threaded through explicitly. -
VozduxanConfig.log_userdatais a raw pointer into theArc<AppDebugLog>kept alive byVozduxanSessionInner._debug_log_arc. Do not drop the Arc while the vozduxan session is live. -
The
metadata_received_alertlibtorrent alert is not fired whenatp.tiis already set (i.e., when a.torrentfile is provided rather than a magnet). vozduxan handles this case internally in C++. Do not add a workaround on the Rust side. -
build.rsenumerates individual C++ source files withcargo:rerun-if-changedbecause macOS does not bump directory mtime when a file inside it changes. -
The resolver's Brave source enforces
site:genius.comclient-side too — Brave honours the operator loosely and returns off-topic results (YouTube, Apple Music, blogs).brave.rsdrops any result whose page title does not end withGenius.
Where to go next¶
- To understand how a track goes from user click to audio playback: Streaming — Vozduxan Engine
- To understand how a query becomes a canonical artist/title pair: Query Resolver — Overview
- To understand the search result pipeline: Search Pipeline — SearchSession
- To understand how cookies, magnet links, and torrent files are managed: RuTracker — Authentication
- To understand the SoulSeek binary protocol: SoulSeek — Binary Protocol