CLI `play --uri <album/playlist/artist/show> --queue` replaces playback instead of queueing
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
調査の方向性
parse_spotify_uri の近くにある src/cli/clap.rs から始め、小さな純粋ヘルパー check_play_uri_flags を追加してください。このヘルパーは、トラック以外の URI に対する --queue と、プレイリスト以外の URI に対する --random を拒否します。src/cli/handle.rs の "play" アームにある --uri 分岐で、cli.play_uri(...) の前にこれを呼び出し、エラーは ? で伝播させてください。clap.rs の mod tests ブロックに play_uri_flags_* という名前のテストを追加します。cargo test --no-default-features --features telemetry,tui play_uri_flags で新しいテストが実行され、それらが合格し、不正な組み合わせが再生を開始せずにゼロ以外の終了コードで終了すれば完了です。
索引モデルが issue の本文から書いたものです。
説明
What
spotatui play --uri accepts --queue and --random with every URI kind, but each flag only works with one kind. With any other kind the flag is silently ignored.
How to reproduce:
- Start something playing.
- Run
spotatui play --uri spotify:album:<id> --queue. Swapping in a playlist, artist or show URI gives the same result. - The album starts right away and replaces what was playing. Nothing gets queued.
- Run
spotatui play --uri spotify:album:<id> --random. The album plays from the first track, with no warning.
The help already says what should happen: --queue "Adds track to queue instead of playing it directly", and --random "Plays a random track (only works with playlists)". So we want:
--queuewith a URI that isn't aspotify:track:URI fails with a clear error and a non-zero exit code.--randomwith a URI that isn't aspotify:playlist:URI does the same.- Neither case should start or change playback.
The cause: clap only blocks these combinations for the play --name NAME path, through conflicts_with_all on the --album/--artist/--playlist/--show/--track flags. A --uri only shows its kind inside the string, so clap can't catch it. play_uri then reads queue in the track branch only and random for playlists only.
Where to look
src/cli/clap.rs, lines 244-261: thequeueandrandomargs. Their conflicts only cover the--namecategory flags, neveruri:Arg::new("queue") ... // Only works with tracks .conflicts_with_all(["album", "artist", "playlist", "show"]) .help("Adds track to queue instead of playing it directly"),Arg::new("random") ... // Only works with playlists .conflicts_with_all(["track", "album", "artist", "show"]) .help("Plays a random track (only works with playlists)"),src/cli/clap.rs, lines 228-235: theuriarg uses.value_parser(parse_spotify_uri).src/cli/clap.rs, lines 25-44:fn parse_spotify_uri(uri: &str) -> Result<String, String>. It already guarantees that a URI reaching the handler starts with one ofspotify:track:,spotify:album:,spotify:artist:,spotify:playlist:orspotify:show:(thePLAYABLElist, checked withstarts_with). Your new helper goes right next to it.src/cli/clap.rs, lines 435-480: themod testsblock. It holdsplay_uri_accepts_the_spotify_kinds_it_can_start(440),play_uri_refuses_another_source_and_names_its_scheme(456) andplay_uri_refuses_a_spotify_kind_it_cannot_start(469). Your tests go here.src/cli/handle.rs, lines 141-154: the"play"arm ofhandle_matches:let queue = matches.get_flag("queue"); let random = matches.get_flag("random"); ... if let Some(uri) = matches.get_one::<String>("uri") { cli.play_uri(uri.to_string(), queue, random).await; } else if let Some(name) = matches.get_one::<String>("name") {handle_matches(line 53) returnsResult<String>, so anErrhere makes the CLI exit non-zero.anyhowandanyhow!are already imported at line 9.src/cli/cli_app.rs, lines 434-520:pub async fn play_uri(&mut self, uri: String, queue: bool, random: bool).- Random is honored only under
if uri.contains("spotify:playlist:")(line 437). Every other URI getsNone(lines 489-491). queueis read only in the track branch (lines 497-508):if queue { ... IoEvent::AddItemToQueue(uri) } else { ... }.- The context branch (lines 509-519) always sends
IoEvent::StartPlayback(Some(uri), None, offset), whateverqueuesays. That's the bug.
- Random is honored only under
src/cli/cli_app.rs, lines 523-539:CliApp::play(the--namepath) also callsself.play_uri(uri, queue, random)at line 536. Clap already guards that path.
Possible solution
- Add a small pure helper in
src/cli/clap.rs, next toparse_spotify_uri:/// Refuses a `--queue` or `--random` that the `--uri` kind cannot honor. pub(super) fn check_play_uri_flags(uri: &str, queue: bool, random: bool) -> Result<(), String> { if queue && !uri.starts_with("spotify:track:") { return Err("--queue works only with a spotify:track: URI".to_string()); } if random && !uri.starts_with("spotify:playlist:") { return Err("--random works only with a spotify:playlist: URI".to_string()); } Ok(()) }- It must be at least
pub(super).mod clap;is private insrc/cli/mod.rs, andparse_spotify_uriis a private fn, sohandle.rsreaches the helper assuper::clap::check_play_uri_flags. - Use
starts_with, notcontains, to matchparse_spotify_uri. Result<(), String>matches the style already inclap.rs. Returninganyhow::Result<()>is fine too, if you prefer it.
- It must be at least
- Call it in
src/cli/handle.rs, inside the--uribranch and beforecli.play_uri(...), so nothing reaches Spotify when the flags don't fit:
You can also addif let Some(uri) = matches.get_one::<String>("uri") { super::clap::check_play_uri_flags(uri, queue, random).map_err(|e| anyhow!(e))?; cli.play_uri(uri.to_string(), queue, random).await; }clap::check_play_uri_flagsto theuse super::{...}block at the top ofhandle.rs(lines 4-7) and call it by its short name. - Traps and things to leave alone:
- Don't put the check inside
play_uri. The--namepath (CliApp::play, line 536) also goes through it, and clap already guards that path. - Don't change
play_uri's signature. It returns()and reports its own errors throughhandle_error. - No
println!oreprintln!for the message.src/cli/AGENTS.mdsays stdout is for command output only. Return the error and let the caller report it. --uri spotify:track:X --queueand--uri spotify:playlist:X --randommust keep working exactly as they do now.- Leave the "Development Mode" comment at
cli_app.rslines 452-453 alone. It's out of scope for this issue. - Queueing a whole album could be a nice feature later. This issue only turns the unsupported combination into an error.
- Don't put the check inside
- Tests to add, in the
mod testsblock ofsrc/cli/clap.rs(line 436). They call the pure helper directly, so they don't need a Spotify account, a network or an audio device. Make every test name containplay_uri_flagsso the filter below picks them up:play_uri_flags_refuse_queue_with_an_album_uri:check_play_uri_flags("spotify:album:1", true, false)isErr, and the message contains--queue. Loop overalbum,artist,playlistandshowif you like.play_uri_flags_refuse_random_with_a_non_playlist_uri:("spotify:artist:1", false, true)and("spotify:track:1", false, true)areErr, and the message contains--random.play_uri_flags_allow_queue_with_a_track_uri:("spotify:track:1", true, false)isOk(()).play_uri_flags_allow_random_with_a_playlist_uri:("spotify:playlist:1", false, true)isOk(()).play_uri_flags_allow_any_kind_without_flags: every kind with(false, false)isOk(()).
- CI runs clippy on the bin target only, so run cargo test to compile test code.
- Leave tools/gates.count alone, new tests need no counter change.
Done when
cargo test --no-default-features --features telemetry,tui play_uri_flagsruns your new tests and they pass. A filter that matches nothing still exits 0, so check the count.- Manual check (needs a Spotify login, so this one is optional):
spotatui play --uri spotify:album:<id> --queueprints the--queueerror, exits non-zero and leaves playback alone.spotatui play --uri spotify:track:<id> --queuestill queues the track. - cargo fmt --all -- --check, cargo clippy --no-default-features --features telemetry,tui -- -D warnings and cargo test --no-default-features --features telemetry,tui pass.
- 主要言語
- Rust
- スター
- 1.4k
- フォーク
- 238
- 平均マージ
- 8時間 56分
- マージ済み PR(30日)
- 208
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
LargeModGames/spotatui のほかの issue
-
bug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
LargeModGames/spotatui#878 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 90/100
LargeModGames/spotatui#872 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
bug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 92/100
LargeModGames/spotatui#871 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
documentation good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
LargeModGames/spotatui#832 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
bug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
LargeModGames/spotatui#829 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
LargeModGames/spotatui の issue をすべて見る
似ている issue
-
test: sim_zero_omega_tests race on shared temp-file names, so two pairs of tests fail at randomオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
pop-os/cosmic-comp#2956 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
area:release criticality:p3 documentation
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
registrystack/registry-stack#2085 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
libp2p/rust-libp2p#6694 ·
メンテナーはふだん 1 日以内に返信