feat: add YouTube search to !play and fix NA URL fallback
Non-URL input (e.g. !play classical music) searches YouTube for 10 results and picks one randomly. Also fixes --flat-playlist returning "NA" as the URL for single videos by falling back to the original input URL.
This commit is contained in:
@@ -134,6 +134,25 @@ class TestPlayCommand:
|
||||
assert len(ps["queue"]) == 1
|
||||
assert ps["queue"][0].title == "Test Track"
|
||||
|
||||
def test_play_search_query(self):
|
||||
bot = _FakeBot()
|
||||
msg = _Msg(text="!play classical music")
|
||||
tracks = [
|
||||
("https://youtube.com/watch?v=a", "Result 1"),
|
||||
("https://youtube.com/watch?v=b", "Result 2"),
|
||||
("https://youtube.com/watch?v=c", "Result 3"),
|
||||
]
|
||||
with patch.object(_mod, "_resolve_tracks", return_value=tracks) as mock_rt:
|
||||
with patch.object(_mod, "_ensure_loop"):
|
||||
asyncio.run(_mod.cmd_play(bot, msg))
|
||||
# Should prepend ytsearch10: for non-URL input
|
||||
mock_rt.assert_called_once()
|
||||
assert mock_rt.call_args[0][0] == "ytsearch10:classical music"
|
||||
# Should pick one random result, not enqueue all
|
||||
ps = _mod._ps(bot)
|
||||
assert len(ps["queue"]) == 1
|
||||
assert any("Playing" in r for r in bot.replied)
|
||||
|
||||
def test_play_shows_queued_when_busy(self):
|
||||
bot = _FakeBot()
|
||||
ps = _mod._ps(bot)
|
||||
@@ -354,6 +373,21 @@ class TestMusicHelpers:
|
||||
assert len(result) == 80
|
||||
assert result.endswith("...")
|
||||
|
||||
def test_is_url_http(self):
|
||||
assert _mod._is_url("https://youtube.com/watch?v=abc") is True
|
||||
|
||||
def test_is_url_plain_http(self):
|
||||
assert _mod._is_url("http://example.com") is True
|
||||
|
||||
def test_is_url_ytsearch(self):
|
||||
assert _mod._is_url("ytsearch:classical music") is True
|
||||
|
||||
def test_is_url_search_query(self):
|
||||
assert _mod._is_url("classical music") is False
|
||||
|
||||
def test_is_url_single_word(self):
|
||||
assert _mod._is_url("jazz") is False
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# TestPlaylistExpansion
|
||||
@@ -431,6 +465,14 @@ class TestPlaylistExpansion:
|
||||
tracks = _mod._resolve_tracks("https://example.com/v1")
|
||||
assert tracks == [("https://example.com/v1", "Single Video")]
|
||||
|
||||
def test_resolve_tracks_na_url_fallback(self):
|
||||
"""--flat-playlist prints NA for single videos; use original URL."""
|
||||
result = MagicMock()
|
||||
result.stdout = "NA\nSingle Video\n"
|
||||
with patch("subprocess.run", return_value=result):
|
||||
tracks = _mod._resolve_tracks("https://example.com/v1")
|
||||
assert tracks == [("https://example.com/v1", "Single Video")]
|
||||
|
||||
def test_resolve_tracks_playlist(self):
|
||||
"""Subprocess returning multiple url+title pairs."""
|
||||
result = MagicMock()
|
||||
|
||||
Reference in New Issue
Block a user