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:
@@ -3,6 +3,8 @@
|
||||
//! Each command opens a [`Session`], does one job, writes records to stdout
|
||||
//! and progress to stderr, and returns an exit code through [`CliError`].
|
||||
|
||||
pub mod peer;
|
||||
pub mod settings;
|
||||
pub mod social;
|
||||
pub mod transfer;
|
||||
|
||||
@@ -171,6 +173,9 @@ pub fn run(ctx: &Ctx, command: Commands) -> CliResult {
|
||||
Commands::Room(RoomCommand::Say { room, message }) => {
|
||||
social::room_say(ctx, &room, &message)
|
||||
}
|
||||
Commands::Room(RoomCommand::Users { room, timeout }) => {
|
||||
social::room_users(ctx, &room, Duration::from_secs(timeout))
|
||||
}
|
||||
Commands::Room(RoomCommand::Listen {
|
||||
room,
|
||||
duration,
|
||||
@@ -182,8 +187,15 @@ pub fn run(ctx: &Ctx, command: Commands) -> CliResult {
|
||||
Commands::Message(MessageCommand::Read { duration, follow }) => {
|
||||
social::message_read(ctx, listen_span(duration, follow))
|
||||
}
|
||||
// Handled before credentials are required; see main.rs.
|
||||
Commands::Serve(args) => peer::serve(ctx, &args),
|
||||
Commands::User(args) => peer::user(ctx, &args),
|
||||
Commands::Whoami => peer::whoami(ctx),
|
||||
// These need no account, so main.rs answers them before asking for
|
||||
// credentials; the arms exist only to keep the match exhaustive.
|
||||
Commands::Portmap => portmap(&ctx.out, ctx.settings.listen_port),
|
||||
Commands::Config(_) | Commands::Shares(_) => {
|
||||
Err(CliError::usage("handled without a session; see main::run"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user