From 7bf2748e1fe39b119dae0d2b2bf136ee34cfde80 Mon Sep 17 00:00:00 2001 From: Michel de Graaf Date: Tue, 11 Nov 2025 21:51:11 +0100 Subject: [PATCH] feat: seperate into lib and cli packages --- Cargo.lock | 7 + Cargo.toml | 13 +- README.md | 52 ++++++-- RELEASE.md | 122 ++++++++++++++++++ soulseek-rs-lib/Cargo.toml | 20 +++ soulseek-rs-lib/README.md | 55 ++++++++ {src => soulseek-rs-lib/src}/actor/mod.rs | 0 .../src}/actor/peer_actor.rs | 0 .../src}/actor/peer_registry.rs | 0 .../src}/actor/server_actor.rs | 0 {src => soulseek-rs-lib/src}/client.rs | 0 {src => soulseek-rs-lib/src}/dispatcher.rs | 0 {src => soulseek-rs-lib/src}/error.rs | 0 {src => soulseek-rs-lib/src}/lib.rs | 0 .../src}/message/handlers.rs | 0 .../src}/message/message_reader.rs | 0 {src => soulseek-rs-lib/src}/message/mod.rs | 0 .../src}/message/peer/file_search_response.rs | 0 .../src}/message/peer/get_share_file_list.rs | 0 .../src}/message/peer/mod.rs | 0 .../src}/message/peer/peer_init.rs | 0 .../message/peer/place_in_queue_response.rs | 0 .../src}/message/peer/transfer_request.rs | 0 .../src}/message/peer/transfer_response.rs | 0 .../src}/message/peer/upload_failed.rs | 0 .../src}/message/server/connect_to_peer.rs | 0 .../message/server/excluded_search_phrases.rs | 0 .../src}/message/server/file_search.rs | 0 .../src}/message/server/get_peer_address.rs | 0 .../src}/message/server/login.rs | 0 .../src}/message/server/message_factory.rs | 0 .../src}/message/server/message_user.rs | 0 .../src}/message/server/mod.rs | 0 .../src}/message/server/parent_min_speed.rs | 0 .../src}/message/server/parent_speed_ratio.rs | 0 .../src}/message/server/privileged_users.rs | 0 .../src}/message/server/room_list.rs | 0 .../src}/message/server/wish_list_interval.rs | 0 .../src}/peer/download_peer.rs | 0 {src => soulseek-rs-lib/src}/peer/listen.rs | 0 {src => soulseek-rs-lib/src}/peer/mod.rs | 0 {src => soulseek-rs-lib/src}/types.rs | 0 {src => soulseek-rs-lib/src}/utils/logger.rs | 0 {src => soulseek-rs-lib/src}/utils/md5.rs | 0 {src => soulseek-rs-lib/src}/utils/mod.rs | 0 .../src}/utils/thread_pool.rs | 0 {src => soulseek-rs-lib/src}/utils/zlib.rs | 0 soulseek-rs/Cargo.toml | 23 ++++ soulseek-rs/README.md | 26 ++++ soulseek-rs/src/main.rs | 34 +++++ src/main.rs | 52 -------- 51 files changed, 334 insertions(+), 70 deletions(-) create mode 100644 RELEASE.md create mode 100644 soulseek-rs-lib/Cargo.toml create mode 100644 soulseek-rs-lib/README.md rename {src => soulseek-rs-lib/src}/actor/mod.rs (100%) rename {src => soulseek-rs-lib/src}/actor/peer_actor.rs (100%) rename {src => soulseek-rs-lib/src}/actor/peer_registry.rs (100%) rename {src => soulseek-rs-lib/src}/actor/server_actor.rs (100%) rename {src => soulseek-rs-lib/src}/client.rs (100%) rename {src => soulseek-rs-lib/src}/dispatcher.rs (100%) rename {src => soulseek-rs-lib/src}/error.rs (100%) rename {src => soulseek-rs-lib/src}/lib.rs (100%) rename {src => soulseek-rs-lib/src}/message/handlers.rs (100%) rename {src => soulseek-rs-lib/src}/message/message_reader.rs (100%) rename {src => soulseek-rs-lib/src}/message/mod.rs (100%) rename {src => soulseek-rs-lib/src}/message/peer/file_search_response.rs (100%) rename {src => soulseek-rs-lib/src}/message/peer/get_share_file_list.rs (100%) rename {src => soulseek-rs-lib/src}/message/peer/mod.rs (100%) rename {src => soulseek-rs-lib/src}/message/peer/peer_init.rs (100%) rename {src => soulseek-rs-lib/src}/message/peer/place_in_queue_response.rs (100%) rename {src => soulseek-rs-lib/src}/message/peer/transfer_request.rs (100%) rename {src => soulseek-rs-lib/src}/message/peer/transfer_response.rs (100%) rename {src => soulseek-rs-lib/src}/message/peer/upload_failed.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/connect_to_peer.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/excluded_search_phrases.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/file_search.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/get_peer_address.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/login.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/message_factory.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/message_user.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/mod.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/parent_min_speed.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/parent_speed_ratio.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/privileged_users.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/room_list.rs (100%) rename {src => soulseek-rs-lib/src}/message/server/wish_list_interval.rs (100%) rename {src => soulseek-rs-lib/src}/peer/download_peer.rs (100%) rename {src => soulseek-rs-lib/src}/peer/listen.rs (100%) rename {src => soulseek-rs-lib/src}/peer/mod.rs (100%) rename {src => soulseek-rs-lib/src}/types.rs (100%) rename {src => soulseek-rs-lib/src}/utils/logger.rs (100%) rename {src => soulseek-rs-lib/src}/utils/md5.rs (100%) rename {src => soulseek-rs-lib/src}/utils/mod.rs (100%) rename {src => soulseek-rs-lib/src}/utils/thread_pool.rs (100%) rename {src => soulseek-rs-lib/src}/utils/zlib.rs (100%) create mode 100644 soulseek-rs/Cargo.toml create mode 100644 soulseek-rs/README.md create mode 100644 soulseek-rs/src/main.rs delete mode 100644 src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 4bc772f..e8e8c8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,3 +5,10 @@ version = 4 [[package]] name = "soulseek-rs" version = "0.1.0" +dependencies = [ + "soulseek-rs-lib", +] + +[[package]] +name = "soulseek-rs-lib" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index fbba1f9..935a92e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,10 @@ -[package] -name = "soulseek-rs" -version = "0.1.0" -edition = "2021" +[workspace] +members = ["soulseek-rs-lib", "soulseek-rs"] +resolver = "2" +[workspace.package] +version = "0.1.0" +authors = ["Michel de Graaf"] +edition = "2021" +license = "MIT OR Apache-2.0" +repository = "https://github.com/yourusername/soulseek-rs" diff --git a/README.md b/README.md index dcda68f..88fc2a5 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ ## ⚠️WARNING THIS IS UNDER DEVELOPMENT AND NOT READY FOR USE ⚠️ -Souleek-rs is an experimental Soulseek client built in Rust. It's under -development and not yet ready for use. Soulseek is a closed-source P2P +Souleek-rs is an experimental Soulseek library and client built in Rust. It's +under development and not yet ready for use. Soulseek is a closed-source P2P file-sharing network from the 2000s. It's still used by music enthusiasts around the world to share niche music. @@ -17,9 +17,12 @@ about asynchronous and concurrent network programming and reverse engineering It's not intended to be a production-ready client (yet). Since it's a learning project, I have a self-imposed restriction not to use -external dependencies. This means I can't use any external crates that are not -part of the Rust standard library. This is a good challenge to learn how to -build complex systems with only the standard library. +external dependencies in the library. This means I can't use any external +crates that are not part of the Rust standard library. This is a good challenge +to learn how to build complex systems with only the standard library. + +In the client crate, external dependencies are allowed for building a rich +experience. For me, this is a good balance between learning and practicality. ## Planned Features @@ -33,18 +36,30 @@ build complex systems with only the standard library. - [ ] Private messaging - [ ] Headless mode daemon mode with remote control -## Project structure +## Project Structure -Soulseek-rs is planned to be structured as a generic reusable library -(soulseek-rs-lib) with a CLI client (soulseek-rs). +This project is organized as a Cargo workspace with two crates: -The CLI client will have a simple command-line interface to interact with the -library. A rich TUI mode will be added in the future. +- **soulseek-rs-lib** - The core library implementing the Soulseek protocol +- **soulseek-rs** - A CLI client built on top of the library + +This structure allows: + +- Other developers to build custom Soulseek clients using `soulseek-rs-lib` +- Users to install the ready-made client via `cargo install soulseek-rs` +- Clean separation of concerns between protocol implementation and user interface ## Installation -To install Soulseek-rs, you'll need to have Rust installed on your system. Then, -you can clone the repository and build it with cargo: +### For Users + +```bash +cargo install soulseek-rs +``` + +### For Developers + +Clone and build from source: ```bash git clone git@github.com:michel/soulseek-rs.git @@ -52,12 +67,21 @@ cd soulseek-rs cargo build --release ``` -The binary will be available at `target/release/soulseek-rs`. +The binary will be available at `target/release/soulseek`. + +### For Library Users + +To build your own Soulseek client, add to your `Cargo.toml`: + +```toml +[dependencies] +soulseek-rs-lib = "0.1.0" +``` ## Usage ```bash -./target/release/soulseek-rs "the weeknd Blinding Lights" +./target/release/soulseek "the weeknd Blinding Lights" ``` ## Development diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000..6422176 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,122 @@ +# Release Guide + +This guide explains how to publish the `soulseek-rs-lib` and `soulseek-rs` crates to crates.io. + +## Prerequisites + +1. Create an account on [crates.io](https://crates.io/) +2. Generate an API token: https://crates.io/me +3. Login to cargo: `cargo login ` + +## Publishing Process + +### Step 1: Publish the Library First + +The client depends on the library, so the library must be published first. + +```bash +cd soulseek-rs-lib +cargo publish --dry-run # Test the publish +cargo publish # Actually publish +``` + +### Step 2: Wait for crates.io to Index + +After publishing the library, wait 1-2 minutes for crates.io to index it before publishing the client. + +### Step 3: Update Client Dependency (for releases) + +When publishing to crates.io, the client's `Cargo.toml` should reference the published library version, not the local path. + +Edit `soulseek-rs/Cargo.toml`: + +```toml +[dependencies] +# For local development: +soulseek-rs-lib = { version = "0.1.0", path = "../soulseek-rs-lib" } + +# For publishing (comment out path): +# soulseek-rs-lib = "0.1.0" +``` + +Or use both with optional features: + +```toml +[dependencies] +soulseek-rs-lib = "0.1.0" + +[dev-dependencies] +soulseek-rs-lib = { version = "0.1.0", path = "../soulseek-rs-lib" } +``` + +### Step 4: Publish the Client + +```bash +cd ../soulseek-rs +cargo publish --dry-run # Test the publish +cargo publish # Actually publish +``` + +## Version Management + +When bumping versions: + +1. Update the version in root `Cargo.toml` under `[workspace.package]` +2. Both crates will inherit this version automatically +3. Publish library first, then client + +## Automated Releases (Optional) + +You can automate this with GitHub Actions. Create `.github/workflows/release.yml`: + +```yaml +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - name: Publish library + run: | + cd soulseek-rs-lib + cargo publish --token ${{ secrets.CARGO_TOKEN }} + + - name: Wait for crates.io + run: sleep 60 + + - name: Publish client + run: | + cd soulseek-rs + cargo publish --token ${{ secrets.CARGO_TOKEN }} +``` + +## Testing Installation + +After publishing, test the installation: + +```bash +cargo install soulseek-rs +soulseek --help # Should work +``` + +## For Developers Building Custom Clients + +Developers can use the library by adding to their `Cargo.toml`: + +```toml +[dependencies] +soulseek-rs-lib = "0.1.0" +``` + +They'll get access to all the types and functionality exported in `lib.rs`. diff --git a/soulseek-rs-lib/Cargo.toml b/soulseek-rs-lib/Cargo.toml new file mode 100644 index 0000000..96181f1 --- /dev/null +++ b/soulseek-rs-lib/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "soulseek-rs-lib" +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +description = "Library for Soulseek protocol implementation in Rust" +keywords = ["soulseek", "p2p", "protocol", "file-sharing"] +categories = ["network-programming"] + +[lib] +name = "soulseek_rs" +path = "src/lib.rs" + +[dependencies] +# Add your dependencies here as needed +# For example: +# tokio = { version = "1", features = ["full"] } +# serde = { version = "1", features = ["derive"] } diff --git a/soulseek-rs-lib/README.md b/soulseek-rs-lib/README.md new file mode 100644 index 0000000..607aecc --- /dev/null +++ b/soulseek-rs-lib/README.md @@ -0,0 +1,55 @@ +# soulseek-rs-lib + +A Rust library for implementing the Soulseek peer-to-peer protocol. + +## About + +This library provides the core functionality for interacting with the Soulseek +network. It can be used to build custom Soulseek clients or bots. + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +soulseek-rs-lib = "0.1.0" +``` + +## Example + +```rust +use soulseek_rs::{Client, PeerAddress}; +use std::time::Duration; + +fn main() -> Result<(), Box> { + // Create and connect to Soulseek server + let mut client = Client::new( + PeerAddress::new("server.slsknet.org".to_string(), 2242), + "username".to_string(), + "password".to_string(), + false, + None, + ); + + client.connect(); + client.login()?; + + // Search for files + let results = client.search("Alex Kassian lifestream", Duration::from_secs(10))?; + + // Download first available file + if let Some(result) = results.iter().find(|r| !r.files.is_empty()) { + let file = &result.files[0]; + client.download( + file.name.clone(), + file.username.clone(), + file.size, + "~/Downloads".to_string(), + )?; + println!("Downloaded: {}", file.name); + } + + Ok(()) +} +``` diff --git a/src/actor/mod.rs b/soulseek-rs-lib/src/actor/mod.rs similarity index 100% rename from src/actor/mod.rs rename to soulseek-rs-lib/src/actor/mod.rs diff --git a/src/actor/peer_actor.rs b/soulseek-rs-lib/src/actor/peer_actor.rs similarity index 100% rename from src/actor/peer_actor.rs rename to soulseek-rs-lib/src/actor/peer_actor.rs diff --git a/src/actor/peer_registry.rs b/soulseek-rs-lib/src/actor/peer_registry.rs similarity index 100% rename from src/actor/peer_registry.rs rename to soulseek-rs-lib/src/actor/peer_registry.rs diff --git a/src/actor/server_actor.rs b/soulseek-rs-lib/src/actor/server_actor.rs similarity index 100% rename from src/actor/server_actor.rs rename to soulseek-rs-lib/src/actor/server_actor.rs diff --git a/src/client.rs b/soulseek-rs-lib/src/client.rs similarity index 100% rename from src/client.rs rename to soulseek-rs-lib/src/client.rs diff --git a/src/dispatcher.rs b/soulseek-rs-lib/src/dispatcher.rs similarity index 100% rename from src/dispatcher.rs rename to soulseek-rs-lib/src/dispatcher.rs diff --git a/src/error.rs b/soulseek-rs-lib/src/error.rs similarity index 100% rename from src/error.rs rename to soulseek-rs-lib/src/error.rs diff --git a/src/lib.rs b/soulseek-rs-lib/src/lib.rs similarity index 100% rename from src/lib.rs rename to soulseek-rs-lib/src/lib.rs diff --git a/src/message/handlers.rs b/soulseek-rs-lib/src/message/handlers.rs similarity index 100% rename from src/message/handlers.rs rename to soulseek-rs-lib/src/message/handlers.rs diff --git a/src/message/message_reader.rs b/soulseek-rs-lib/src/message/message_reader.rs similarity index 100% rename from src/message/message_reader.rs rename to soulseek-rs-lib/src/message/message_reader.rs diff --git a/src/message/mod.rs b/soulseek-rs-lib/src/message/mod.rs similarity index 100% rename from src/message/mod.rs rename to soulseek-rs-lib/src/message/mod.rs diff --git a/src/message/peer/file_search_response.rs b/soulseek-rs-lib/src/message/peer/file_search_response.rs similarity index 100% rename from src/message/peer/file_search_response.rs rename to soulseek-rs-lib/src/message/peer/file_search_response.rs diff --git a/src/message/peer/get_share_file_list.rs b/soulseek-rs-lib/src/message/peer/get_share_file_list.rs similarity index 100% rename from src/message/peer/get_share_file_list.rs rename to soulseek-rs-lib/src/message/peer/get_share_file_list.rs diff --git a/src/message/peer/mod.rs b/soulseek-rs-lib/src/message/peer/mod.rs similarity index 100% rename from src/message/peer/mod.rs rename to soulseek-rs-lib/src/message/peer/mod.rs diff --git a/src/message/peer/peer_init.rs b/soulseek-rs-lib/src/message/peer/peer_init.rs similarity index 100% rename from src/message/peer/peer_init.rs rename to soulseek-rs-lib/src/message/peer/peer_init.rs diff --git a/src/message/peer/place_in_queue_response.rs b/soulseek-rs-lib/src/message/peer/place_in_queue_response.rs similarity index 100% rename from src/message/peer/place_in_queue_response.rs rename to soulseek-rs-lib/src/message/peer/place_in_queue_response.rs diff --git a/src/message/peer/transfer_request.rs b/soulseek-rs-lib/src/message/peer/transfer_request.rs similarity index 100% rename from src/message/peer/transfer_request.rs rename to soulseek-rs-lib/src/message/peer/transfer_request.rs diff --git a/src/message/peer/transfer_response.rs b/soulseek-rs-lib/src/message/peer/transfer_response.rs similarity index 100% rename from src/message/peer/transfer_response.rs rename to soulseek-rs-lib/src/message/peer/transfer_response.rs diff --git a/src/message/peer/upload_failed.rs b/soulseek-rs-lib/src/message/peer/upload_failed.rs similarity index 100% rename from src/message/peer/upload_failed.rs rename to soulseek-rs-lib/src/message/peer/upload_failed.rs diff --git a/src/message/server/connect_to_peer.rs b/soulseek-rs-lib/src/message/server/connect_to_peer.rs similarity index 100% rename from src/message/server/connect_to_peer.rs rename to soulseek-rs-lib/src/message/server/connect_to_peer.rs diff --git a/src/message/server/excluded_search_phrases.rs b/soulseek-rs-lib/src/message/server/excluded_search_phrases.rs similarity index 100% rename from src/message/server/excluded_search_phrases.rs rename to soulseek-rs-lib/src/message/server/excluded_search_phrases.rs diff --git a/src/message/server/file_search.rs b/soulseek-rs-lib/src/message/server/file_search.rs similarity index 100% rename from src/message/server/file_search.rs rename to soulseek-rs-lib/src/message/server/file_search.rs diff --git a/src/message/server/get_peer_address.rs b/soulseek-rs-lib/src/message/server/get_peer_address.rs similarity index 100% rename from src/message/server/get_peer_address.rs rename to soulseek-rs-lib/src/message/server/get_peer_address.rs diff --git a/src/message/server/login.rs b/soulseek-rs-lib/src/message/server/login.rs similarity index 100% rename from src/message/server/login.rs rename to soulseek-rs-lib/src/message/server/login.rs diff --git a/src/message/server/message_factory.rs b/soulseek-rs-lib/src/message/server/message_factory.rs similarity index 100% rename from src/message/server/message_factory.rs rename to soulseek-rs-lib/src/message/server/message_factory.rs diff --git a/src/message/server/message_user.rs b/soulseek-rs-lib/src/message/server/message_user.rs similarity index 100% rename from src/message/server/message_user.rs rename to soulseek-rs-lib/src/message/server/message_user.rs diff --git a/src/message/server/mod.rs b/soulseek-rs-lib/src/message/server/mod.rs similarity index 100% rename from src/message/server/mod.rs rename to soulseek-rs-lib/src/message/server/mod.rs diff --git a/src/message/server/parent_min_speed.rs b/soulseek-rs-lib/src/message/server/parent_min_speed.rs similarity index 100% rename from src/message/server/parent_min_speed.rs rename to soulseek-rs-lib/src/message/server/parent_min_speed.rs diff --git a/src/message/server/parent_speed_ratio.rs b/soulseek-rs-lib/src/message/server/parent_speed_ratio.rs similarity index 100% rename from src/message/server/parent_speed_ratio.rs rename to soulseek-rs-lib/src/message/server/parent_speed_ratio.rs diff --git a/src/message/server/privileged_users.rs b/soulseek-rs-lib/src/message/server/privileged_users.rs similarity index 100% rename from src/message/server/privileged_users.rs rename to soulseek-rs-lib/src/message/server/privileged_users.rs diff --git a/src/message/server/room_list.rs b/soulseek-rs-lib/src/message/server/room_list.rs similarity index 100% rename from src/message/server/room_list.rs rename to soulseek-rs-lib/src/message/server/room_list.rs diff --git a/src/message/server/wish_list_interval.rs b/soulseek-rs-lib/src/message/server/wish_list_interval.rs similarity index 100% rename from src/message/server/wish_list_interval.rs rename to soulseek-rs-lib/src/message/server/wish_list_interval.rs diff --git a/src/peer/download_peer.rs b/soulseek-rs-lib/src/peer/download_peer.rs similarity index 100% rename from src/peer/download_peer.rs rename to soulseek-rs-lib/src/peer/download_peer.rs diff --git a/src/peer/listen.rs b/soulseek-rs-lib/src/peer/listen.rs similarity index 100% rename from src/peer/listen.rs rename to soulseek-rs-lib/src/peer/listen.rs diff --git a/src/peer/mod.rs b/soulseek-rs-lib/src/peer/mod.rs similarity index 100% rename from src/peer/mod.rs rename to soulseek-rs-lib/src/peer/mod.rs diff --git a/src/types.rs b/soulseek-rs-lib/src/types.rs similarity index 100% rename from src/types.rs rename to soulseek-rs-lib/src/types.rs diff --git a/src/utils/logger.rs b/soulseek-rs-lib/src/utils/logger.rs similarity index 100% rename from src/utils/logger.rs rename to soulseek-rs-lib/src/utils/logger.rs diff --git a/src/utils/md5.rs b/soulseek-rs-lib/src/utils/md5.rs similarity index 100% rename from src/utils/md5.rs rename to soulseek-rs-lib/src/utils/md5.rs diff --git a/src/utils/mod.rs b/soulseek-rs-lib/src/utils/mod.rs similarity index 100% rename from src/utils/mod.rs rename to soulseek-rs-lib/src/utils/mod.rs diff --git a/src/utils/thread_pool.rs b/soulseek-rs-lib/src/utils/thread_pool.rs similarity index 100% rename from src/utils/thread_pool.rs rename to soulseek-rs-lib/src/utils/thread_pool.rs diff --git a/src/utils/zlib.rs b/soulseek-rs-lib/src/utils/zlib.rs similarity index 100% rename from src/utils/zlib.rs rename to soulseek-rs-lib/src/utils/zlib.rs diff --git a/soulseek-rs/Cargo.toml b/soulseek-rs/Cargo.toml new file mode 100644 index 0000000..9e50dac --- /dev/null +++ b/soulseek-rs/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "soulseek-rs" +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +description = "Command-line client for Soulseek protocol" +keywords = ["soulseek", "p2p", "client", "file-sharing"] +categories = ["command-line-utilities"] + +[[bin]] +name = "soulseek" +path = "src/main.rs" + +[dependencies] +# Depend on your library +soulseek-rs-lib = { version = "0.1.0", path = "../soulseek-rs-lib" } + +# Add client-specific dependencies here +# For example: +# clap = { version = "4", features = ["derive"] } +# anyhow = "1" diff --git a/soulseek-rs/README.md b/soulseek-rs/README.md new file mode 100644 index 0000000..4e0f803 --- /dev/null +++ b/soulseek-rs/README.md @@ -0,0 +1,26 @@ +# soulseek-rs + +A command-line client for the Soulseek peer-to-peer network. + +## Installation + +`bash cargo install soulseek-rs ` + +This will install the `soulseek` binary to your system. + +## Usage + +The client provides a simple interface to search and download files from the +Soulseek network. + +## Building from Source + +````bash git clone https://github.com/yourusername/soulseek-rs cd soulseek-rs +cargo build --release ``` + +## Library + +If you want to build your own Soulseek client, check out the +[soulseek-rs-lib](https://crates.io/crates/soulseek-rs-lib) library crate. + +```` diff --git a/soulseek-rs/src/main.rs b/soulseek-rs/src/main.rs new file mode 100644 index 0000000..acfc30b --- /dev/null +++ b/soulseek-rs/src/main.rs @@ -0,0 +1,34 @@ +use soulseek_rs::{Client, PeerAddress}; +use std::time::Duration; + +fn main() -> Result<(), Box> { + // Create and connect to Soulseek server + let mut client = Client::new( + PeerAddress::new("server.slsknet.org".to_string(), 2242), + "username".to_string(), + "password".to_string(), + false, + None, + ); + + client.connect(); + client.login()?; + + // Search for files + let results = + client.search("Alex Kassian lifestream", Duration::from_secs(10))?; + + // Download first available file + if let Some(result) = results.iter().find(|r| !r.files.is_empty()) { + let file = &result.files[0]; + client.download( + file.name.clone(), + file.username.clone(), + file.size, + "~/Downloads".to_string(), + )?; + println!("Downloaded: {}", file.name); + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index aef5167..0000000 --- a/src/main.rs +++ /dev/null @@ -1,52 +0,0 @@ -fn main() { - use soulseek_rs::{Client, PeerAddress}; - use std::time::Duration; - - let mut client = Client::new( - PeerAddress::new(String::from("server.slsknet.org"), 2242), - String::from("xxxxxx"), - String::from("xxxxxx"), - false, - None, - ); - - client.connect(); - match client.login() { - Ok(_) => { - match client - .search("Eternity Alex Kassian", Duration::from_secs(30)) - { - Ok(results) => { - if let Some(result) = - results.iter().find(|r| !r.files.is_empty()) - { - let file = result.files[0].clone(); - match client.download( - file.name, - file.username, - file.size, - "~/Downloads".to_string(), - ) { - Ok(download_result) => { - println!( - "Download result: {download_result:?}" - ); - } - Err(e) => { - eprintln!("Failed to download: {e}"); - } - } - } else { - eprint!("No results"); - } - } - Err(e) => { - eprintln!("Failed to search: {e}"); - } - } - } - Err(e) => { - eprintln!("Failed to login: {}", e); - } - } -}