feat!: wishlist, upload-queue privilege recognition, and search filters (#20)
Closes the last two gaps in Soulseek's list of features an alternative client must implement to be tolerated, and adds the result filters Nicotine+ has had all along. Wishlist: server code 103 is sent and code 104's announced interval is kept rather than logged and discarded, so the re-search timer runs off the schedule the server set. `wish add|remove|list|run` plus `serve --wishlist`; wishes persist in config.toml as a TOML array so a comma inside a query survives. `wish run` prints search-shaped records, so it pipes into `download --stdin`. Privilege recognition: the code-69 user list is parsed instead of counted and dropped, and code 92 answers `whoami` as `privilege_seconds`. Uploads now go through a queue with a slot cap (`--upload-slots`, default 2) that serves privileged users first — the cap is what makes the ordering mean anything, so they are one change. `PlaceInQueueRequest` (peer code 51) is answered, where it previously had no handler at all, and a departed peer's slot is released so a stalled peer cannot wedge uploads shut. Search filters: `--exclude`, `--extension`, `--min-size`, `--max-size` beside the existing `--min-bitrate` and `--free-slots`, in one flattened arg group shared by `search`, `get` and `wish run`. Also serialises the library e2e suite behind the same gate `cli_e2e` already uses: the new queue tests hold peer sockets open on purpose, which starved concurrently-spawned soulfinds and failed unrelated download tests with `login: Timeout`. BREAKING CHANGE: `UploadStatus` gains a `Queued(u32)` variant, so an exhaustive match on it no longer compiles, and `cli::Commands` gains `Wish`.
This commit is contained in:
@@ -2,9 +2,10 @@ use crate::actor::{Actor, ActorHandle, ConnectionState};
|
||||
use crate::client::ClientOperation;
|
||||
use crate::dispatcher::MessageDispatcher;
|
||||
use crate::message::peer::{
|
||||
FileSearchResponse, GetShareFileList, PeerInit, PlaceInQueueResponse,
|
||||
QueueUploadHandler, SharedDirectory, SharedFileListResponseHandler,
|
||||
TransferRequest, TransferResponse, UploadFailedHandler,
|
||||
FileSearchResponse, GetShareFileList, PeerInit, PlaceInQueueRequest,
|
||||
PlaceInQueueResponse, QueueUploadHandler, SharedDirectory,
|
||||
SharedFileListResponseHandler, TransferRequest, TransferResponse,
|
||||
UploadFailedHandler,
|
||||
};
|
||||
use crate::message::server::MessageFactory;
|
||||
use crate::message::{Handlers, Message, MessageReader, MessageType};
|
||||
@@ -39,6 +40,8 @@ pub enum PeerMessage {
|
||||
RequestTransfer(Download),
|
||||
/// A peer queued one of our shared files for download (they sent us code 43).
|
||||
IncomingQueueUpload(String),
|
||||
/// A peer asked where their queued file sits (they sent us code 51).
|
||||
IncomingPlaceInQueueRequest(String),
|
||||
/// A peer asked to browse our shared files (they sent us code 4).
|
||||
ShareListRequested,
|
||||
/// A peer we are browsing sent us their shared-file listing (code 5).
|
||||
@@ -164,6 +167,7 @@ impl PeerActor {
|
||||
handlers.register_handler(TransferResponse);
|
||||
handlers.register_handler(GetShareFileList);
|
||||
handlers.register_handler(UploadFailedHandler);
|
||||
handlers.register_handler(PlaceInQueueRequest);
|
||||
handlers.register_handler(PlaceInQueueResponse);
|
||||
handlers.register_handler(QueueUploadHandler);
|
||||
handlers.register_handler(SharedFileListResponseHandler);
|
||||
@@ -235,6 +239,20 @@ impl PeerActor {
|
||||
PeerMessage::IncomingQueueUpload(filename) => {
|
||||
self.handle_incoming_queue_upload(filename);
|
||||
}
|
||||
PeerMessage::IncomingPlaceInQueueRequest(filename) => {
|
||||
let requester_key = self.peer_username();
|
||||
if let Err(e) = self.client_channel.send(
|
||||
ClientOperation::PlaceInQueueRequested {
|
||||
requester_key,
|
||||
filename,
|
||||
},
|
||||
) {
|
||||
error!(
|
||||
"[peer_actor] forward IncomingPlaceInQueueRequest: {}",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
PeerMessage::ServeUpload {
|
||||
token,
|
||||
filename,
|
||||
|
||||
Reference in New Issue
Block a user