feat(cli): expose sharing, peer lookup and settings as one-shot commands
An agent driving the binary could search, fetch and chat, but it could not be a peer: nothing kept a session online to serve files, nothing reported an upload, shares could only be set at startup, and there was no way to ask whether a peer was worth queueing to or to check credentials without doing something else. New commands: serve [--follow] stay online sharing; one record per upload whoami credentials, connection and what we offer user <NAME> a peer's presence and share counts room users <ROOM> the member roster shares list|add|remove|status|reindex config path|list|get|set `config` and `shares list|add|remove` need no account, so they run before the credential check — asking a script to log in for a `config get` would be a poor trade. `serve` is the only place uploads are visible: they live in the process serving them, so a one-shot `uploads list` could print nothing but an empty list. Library additions, all request/poll pairs matching the existing conventions: - Client::room_members, kept current from the join and leave events - Client::request_user_info / user_info, backed by new handlers for GetUserStatus (7) and GetUserStats (36) — codes the dispatcher previously logged as unhandled. The wire format is taken from soulfind's own source and pinned by an e2e test that asserts a peer's real share count. - UserInfo carries presence and stats as Options, so a reply that never arrived cannot be read as "offline" or "shares nothing" - request_user_info clears the previous answer, so the documented poll loop observes this request rather than the last one - ServerMessage and ClientOperation are now #[non_exhaustive]: every protocol message the client learns adds a variant, and that should not break callers - the crate root and prelude re-export every type a Client method returns Also pins the output contract with tests: under --json, stdout carries only newline-delimited JSON across fifteen command shapes while progress still goes to stderr, and a failing command writes nothing to stdout at all.
This commit is contained in:
@@ -129,9 +129,19 @@ soulseek-rs room say <ROOM> <MESSAGE> # post to a room
|
||||
soulseek-rs room listen <ROOM> # stream room messages and joins
|
||||
soulseek-rs message send <USER> <TEXT> # send a private message
|
||||
soulseek-rs message read # stream incoming private messages
|
||||
soulseek-rs room users <ROOM> # who is in a room
|
||||
soulseek-rs serve [--follow] # stay online sharing, stream uploads
|
||||
soulseek-rs whoami # confirm credentials and connection
|
||||
soulseek-rs user <NAME> # a peer's status and share counts
|
||||
soulseek-rs shares list|add|remove|status|reindex
|
||||
soulseek-rs config path|list|get|set
|
||||
soulseek-rs portmap # test automatic port mapping
|
||||
```
|
||||
|
||||
`whoami`, `config` and `shares list|add|remove` are the ones a script runs
|
||||
first: the config commands need no account at all, and `whoami` answers
|
||||
"are these credentials good and what am I offering" in one call.
|
||||
|
||||
Every command emits records except the two that perform an action —
|
||||
`room say` and `message send` say nothing and answer with their exit code
|
||||
alone. `room listen` and `message read` stream records as they arrive, until
|
||||
@@ -180,8 +190,36 @@ fi
|
||||
|
||||
# Log room chat as JSON until interrupted
|
||||
soulseek-rs room listen lobby --follow --json >> lobby.ndjson
|
||||
|
||||
# Be a peer: share a folder and log every upload served
|
||||
soulseek-rs shares add ~/Music
|
||||
soulseek-rs serve --follow --json | tee -a uploads.ndjson
|
||||
|
||||
# Decide whether a peer is worth queueing to before committing
|
||||
soulseek-rs user someuser --json | jq -e '.status != "offline"'
|
||||
```
|
||||
|
||||
### Sharing
|
||||
|
||||
`serve` is the mode that makes this client a source: it stays logged in, keeps
|
||||
the listener and the share index alive, answers searches and browse requests
|
||||
from the network, and prints one record per upload as it changes state
|
||||
(`uploading`, `completed`, `cancelled`, `failed`). It ends after `--duration`
|
||||
seconds, or runs until interrupted with `--follow`.
|
||||
|
||||
```bash
|
||||
soulseek-rs shares add ~/Music # remembered in config.toml
|
||||
soulseek-rs shares status # what the network will actually see
|
||||
soulseek-rs shares reindex # after adding files on disk
|
||||
soulseek-rs serve --follow
|
||||
```
|
||||
|
||||
Uploads are only visible inside a running `serve` — every other command is a
|
||||
short-lived process with nothing to serve — so there is no separate
|
||||
`uploads list`. Managing transfers across commands (pause, resume, a queue
|
||||
that outlives one invocation) needs the resident daemon that `serve` would
|
||||
grow into; it is not there yet.
|
||||
|
||||
Downloads run under a deadline (`--timeout`, 300s by default) and
|
||||
`--max-concurrent-downloads` at a time, so an unattended run always ends.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user