Skip to content

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:

  1. VozduxanStreamState, TorrentImageState, and TorrentStreamState must share the same Arc<AppDebugLog>. They are constructed in lib.rs and the Arc is threaded through explicitly.

  2. VozduxanConfig.log_userdata is a raw pointer into the Arc<AppDebugLog> kept alive by VozduxanSessionInner._debug_log_arc. Do not drop the Arc while the vozduxan session is live.

  3. The metadata_received_alert libtorrent alert is not fired when atp.ti is already set (i.e., when a .torrent file is provided rather than a magnet). vozduxan handles this case internally in C++. Do not add a workaround on the Rust side.

  4. build.rs enumerates individual C++ source files with cargo:rerun-if-changed because macOS does not bump directory mtime when a file inside it changes.

  5. The resolver's Brave source enforces site:genius.com client-side too — Brave honours the operator loosely and returns off-topic results (YouTube, Apple Music, blogs). brave.rs drops any result whose page title does not end with Genius.


Where to go next