aboutsummaryrefslogtreecommitdiffstats
path: root/tests/cogs/test_music_external_play.py
blob: fd4b62518b2fb02951053d08c23f24def7525e3b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import pytest
import os
import asyncio
import tempfile
from unittest.mock import AsyncMock, patch, MagicMock
from tests.conftest import MockApplicationContext


@pytest.fixture
def play_commands_cog(bot):
    with patch('cogs.utils.temp.get_temp_dir', return_value="/tmp"):
        from cogs.music.play_commands import PlayCommands
        cog = PlayCommands(bot)
    return cog


@pytest.fixture
def temp_mp3_file():
    with tempfile.NamedTemporaryFile(suffix='.mp3', delete=False) as f:
        f.write(b'fake mp3 content')
        temp_path = f.name
    yield temp_path
    if os.path.exists(temp_path):
        os.remove(temp_path)


@pytest.mark.asyncio
async def test_external_url_pattern_matches_youtube(play_commands_cog):
    from cogs.music.play_commands import EXTERNAL_URL_PATTERN

    assert EXTERNAL_URL_PATTERN.match("https://youtube.com/watch?v=test")
    assert EXTERNAL_URL_PATTERN.match("https://youtu.be/test")
    assert EXTERNAL_URL_PATTERN.match("https://www.youtube.com/watch?v=test")


@pytest.mark.asyncio
async def test_external_url_pattern_matches_soundcloud(play_commands_cog):
    from cogs.music.play_commands import EXTERNAL_URL_PATTERN

    assert EXTERNAL_URL_PATTERN.match("https://soundcloud.com/artist/track")
    assert EXTERNAL_URL_PATTERN.match("https://api.soundcloud.com/tracks")


@pytest.mark.asyncio
async def test_external_url_pattern_matches_bandcamp(play_commands_cog):
    from cogs.music.play_commands import EXTERNAL_URL_PATTERN

    assert EXTERNAL_URL_PATTERN.match("https://artist.bandcamp.com/track")


@pytest.mark.asyncio
async def test_external_url_pattern_rejects_copyparty(play_commands_cog):
    from cogs.music.play_commands import EXTERNAL_URL_PATTERN

    assert not EXTERNAL_URL_PATTERN.match("https://catbox.2137697.xyz/sperma/file.mp3")
    assert not EXTERNAL_URL_PATTERN.match("some search query")


@pytest.mark.asyncio
async def test_play_command_calls_external_handler(play_commands_cog, mock_channel, mock_guild, bot):
    ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)

    with patch.object(play_commands_cog, '_handle_external_url_play', new_callable=AsyncMock) as mock_handler:
        mock_handler.return_value = None
        mock_defer = AsyncMock()
        ctx.defer = mock_defer
        ctx.respond = AsyncMock()

        await play_commands_cog.play.callback(
            play_commands_cog, ctx,
            melodia="https://youtube.com/watch?v=test",
            file=None, compressed=False
        )

        mock_handler.assert_called_once_with(ctx, "https://youtube.com/watch?v=test")


@pytest.mark.asyncio
async def test_play_command_calls_local_handler(play_commands_cog, mock_channel, mock_guild, bot):
    ctx = MockApplicationContext(bot=bot, channel=mock_channel, guild=mock_guild)

    with patch.object(play_commands_cog, '_handle_local_file_play', new_callable=AsyncMock) as mock_handler:
        mock_handler.return_value = None
        mock_defer = AsyncMock()
        ctx.defer = mock_defer
        ctx.respond = AsyncMock()

        await play_commands_cog.play.callback(
            play_commands_cog, ctx,
            melodia="some search query",
            file=None, compressed=False
        )

        mock_handler.assert_called_once_with(ctx, "some search query", False)


@pytest.mark.asyncio
async def test_upload_to_copyparty_async(play_commands_cog, temp_mp3_file, monkeypatch):
    monkeypatch.setenv("COPYPARTY_URL_UPLOAD", "https://catbox.2137697.xyz/sperma/")
    monkeypatch.setenv("COPYPARTY_PASSWORD", "testpassword")

    mock_response = AsyncMock()
    mock_response.status = 200
    mock_response.text = AsyncMock(return_value="")
    mock_response.json = AsyncMock(return_value={"fileurl": "https://example.com/file.mp3"})
    mock_response.__aenter__ = AsyncMock(return_value=mock_response)
    mock_response.__aexit__ = AsyncMock()

    mock_session_context = AsyncMock()
    mock_session_context.__aenter__ = AsyncMock(return_value=mock_session_context)
    mock_session_context.__aexit__ = AsyncMock()
    mock_session_context.post = MagicMock(return_value=mock_response)

    with patch('aiohttp.ClientSession', return_value=mock_session_context):
        await play_commands_cog._upload_to_copyparty_async(temp_mp3_file)
        mock_session_context.post.assert_called_once()