diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b75c4a0..e93fb77 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false matrix: python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14' ] - rocket-chat-version: [ '7.10.7', '7.11.3', '7.12.4', '7.13.3' , '8.0.1', '8.1.0'] + rocket-chat-version: [ '7.11.6', '7.12.6', '7.13.5' , '8.0.3', '8.1.2', '8.2.1', '8.3.1'] steps: - name: Checkout uses: actions/checkout@v6.0.2 diff --git a/rocketchat_API/APISections/custom_sounds.py b/rocketchat_API/APISections/custom_sounds.py new file mode 100644 index 0000000..3d9ddcb --- /dev/null +++ b/rocketchat_API/APISections/custom_sounds.py @@ -0,0 +1,12 @@ +from rocketchat_API.APISections.base import RocketChatBase, paginated + + +class RocketChatCustomSounds(RocketChatBase): + @paginated("sounds") + def custom_sounds_list(self, **kwargs): + """Retrieves all custom sounds.""" + return self.call_api_get("custom-sounds.list", kwargs=kwargs) + + def custom_sounds_get_one(self, sound_id, **kwargs): + """Retrieves a single custom sound by its _id.""" + return self.call_api_get("custom-sounds.getOne", _id=sound_id, kwargs=kwargs) diff --git a/rocketchat_API/rocketchat.py b/rocketchat_API/rocketchat.py index 2b028f5..bef14c9 100755 --- a/rocketchat_API/rocketchat.py +++ b/rocketchat_API/rocketchat.py @@ -6,6 +6,7 @@ from rocketchat_API.APISections.chat import RocketChatChat from rocketchat_API.APISections.dm import RocketChatDM from rocketchat_API.APISections.custom_emoji import RocketChatCustomEmoji +from rocketchat_API.APISections.custom_sounds import RocketChatCustomSounds from rocketchat_API.APISections.custom_user_status import RocketChatCustomUserStatus from rocketchat_API.APISections.groups import RocketChatGroups from rocketchat_API.APISections.integrations import RocketChatIntegrations @@ -32,6 +33,7 @@ class RocketChat( RocketChatChat, RocketChatDM, RocketChatCustomEmoji, + RocketChatCustomSounds, RocketChatCustomUserStatus, RocketChatGroups, RocketChatIntegrations, diff --git a/tests/conftest.py b/tests/conftest.py index fba6e9b..9e0846e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -78,6 +78,18 @@ def secondary_user(logged_rocket): logged_rocket.users_delete(_testuser_id) +@pytest.fixture +def skip_if_version_under(rocket): + import semver + + def _skip_if_version_under(minimum_version): + parse = lambda v: semver.Version.parse(v, optional_minor_and_patch=True) + if parse(rocket.info()["version"]) < parse(minimum_version): + pytest.skip(f"Requires Rocket.Chat >= {minimum_version}") + + return _skip_if_version_under + + @pytest.fixture def skip_if_no_license(logged_rocket): try: diff --git a/tests/test_custom_sounds.py b/tests/test_custom_sounds.py new file mode 100644 index 0000000..9f6577d --- /dev/null +++ b/tests/test_custom_sounds.py @@ -0,0 +1,79 @@ +import json +import uuid + + +def _sound_name(): + return "test_sound_" + str(uuid.uuid1()).replace("-", "")[:12] + + +def _create_sound(logged_rocket, name): + """Create a custom sound entry via method.call and return its _id.""" + result = logged_rocket.call_api_post( + "method.call/insertOrUpdateSound", + message=json.dumps( + { + "msg": "method", + "id": "1", + "method": "insertOrUpdateSound", + "params": [{"name": name, "extension": "mp3", "newFile": True}], + } + ), + ) + return json.loads(result["message"])["result"] + + +def _delete_sound(logged_rocket, sound_id): + """Delete a custom sound entry via method.call.""" + logged_rocket.call_api_post( + "method.call/deleteCustomSound", + message=json.dumps( + { + "msg": "method", + "id": "1", + "method": "deleteCustomSound", + "params": [sound_id], + } + ), + ) + + +def test_custom_sounds_list(logged_rocket): + result = list(logged_rocket.custom_sounds_list()) + assert isinstance(result, list) + + +def test_custom_sounds_list_structure(logged_rocket): + name = _sound_name() + sound_id = _create_sound(logged_rocket, name) + try: + sounds = list(logged_rocket.custom_sounds_list()) + assert any(s["_id"] == sound_id for s in sounds) + sound = next(s for s in sounds if s["_id"] == sound_id) + assert "name" in sound + assert "extension" in sound + finally: + _delete_sound(logged_rocket, sound_id) + + +def test_custom_sounds_list_filter_by_name(logged_rocket): + name = _sound_name() + sound_id = _create_sound(logged_rocket, name) + try: + sounds = list(logged_rocket.custom_sounds_list(name=name)) + assert len(sounds) >= 1 + assert all(name.lower() in s["name"].lower() for s in sounds) + finally: + _delete_sound(logged_rocket, sound_id) + + +def test_custom_sounds_get_one(logged_rocket, skip_if_version_under): + skip_if_version_under("8.3.0") + name = _sound_name() + sound_id = _create_sound(logged_rocket, name) + try: + result = logged_rocket.custom_sounds_get_one(sound_id) + assert "sound" in result + assert result["sound"]["_id"] == sound_id + assert result["sound"]["name"] == name + finally: + _delete_sound(logged_rocket, sound_id)