gukebox 1.0.0.dev14__tar.gz → 1.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/PKG-INFO +2 -2
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/api/current_tag_router.py +7 -7
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/api/discs_router.py +7 -7
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/api/models.py +1 -1
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/api/settings_router.py +1 -1
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/api_controller.py +10 -10
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/cli_controller.py +10 -10
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/cli_display.py +1 -1
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/interactive_cli_controller.py +7 -7
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/ui_controller.py +34 -177
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/ui_pages/library.py +4 -4
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/admin/app.py +10 -4
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/admin/di_container.py +45 -10
- gukebox-1.0.0.dev14/discstore/command_handlers.py → gukebox-1.0.2/jukebox/admin/library_command_handlers.py +1 -1
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/entities/__init__.py +2 -0
- {gukebox-1.0.0.dev14/discstore/domain/use_cases → gukebox-1.0.2/jukebox/domain/use_cases/library}/add_disc.py +2 -2
- {gukebox-1.0.0.dev14/discstore/domain/use_cases → gukebox-1.0.2/jukebox/domain/use_cases/library}/edit_disc.py +2 -2
- {gukebox-1.0.0.dev14/discstore/domain/use_cases → gukebox-1.0.2/jukebox/domain/use_cases/library}/get_current_tag_status.py +2 -2
- {gukebox-1.0.0.dev14/discstore/domain/use_cases → gukebox-1.0.2/jukebox/domain/use_cases/library}/get_disc.py +2 -2
- {gukebox-1.0.0.dev14/discstore/domain/use_cases → gukebox-1.0.2/jukebox/domain/use_cases/library}/list_discs.py +2 -2
- {gukebox-1.0.0.dev14/discstore/domain/use_cases → gukebox-1.0.2/jukebox/domain/use_cases/library}/remove_disc.py +1 -1
- {gukebox-1.0.0.dev14/discstore/domain/use_cases → gukebox-1.0.2/jukebox/domain/use_cases/library}/resolve_tag_id.py +1 -1
- {gukebox-1.0.0.dev14/discstore/domain/use_cases → gukebox-1.0.2/jukebox/domain/use_cases/library}/search_discs.py +2 -2
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/pyproject.toml +3 -3
- gukebox-1.0.0.dev14/discstore/adapters/inbound/api/__init__.py +0 -25
- gukebox-1.0.0.dev14/discstore/adapters/outbound/json_library_adapter.py +0 -3
- gukebox-1.0.0.dev14/discstore/adapters/outbound/text_current_tag_adapter.py +0 -3
- gukebox-1.0.0.dev14/discstore/di_container.py +0 -42
- gukebox-1.0.0.dev14/discstore/domain/entities/__init__.py +0 -6
- gukebox-1.0.0.dev14/discstore/domain/repositories/__init__.py +0 -4
- gukebox-1.0.0.dev14/discstore/domain/use_cases/__init__.py +0 -19
- gukebox-1.0.0.dev14/jukebox/domain/__init__.py +0 -0
- gukebox-1.0.0.dev14/jukebox/shared/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/LICENSE +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/README.md +0 -0
- {gukebox-1.0.0.dev14/discstore → gukebox-1.0.2/jukebox}/__init__.py +0 -0
- {gukebox-1.0.0.dev14/discstore → gukebox-1.0.2/jukebox}/adapters/__init__.py +0 -0
- {gukebox-1.0.0.dev14/discstore → gukebox-1.0.2/jukebox}/adapters/inbound/__init__.py +0 -0
- {gukebox-1.0.0.dev14/discstore/adapters/inbound/ui_pages → gukebox-1.0.2/jukebox/adapters/inbound/admin}/__init__.py +0 -0
- {gukebox-1.0.0.dev14/discstore/adapters/outbound → gukebox-1.0.2/jukebox/adapters/inbound/admin/api}/__init__.py +0 -0
- {gukebox-1.0.0.dev14/discstore/domain → gukebox-1.0.2/jukebox/adapters/inbound/admin/ui_pages}/__init__.py +0 -0
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/ui_pages/settings.py +0 -0
- {gukebox-1.0.0.dev14/discstore/adapters/inbound → gukebox-1.0.2/jukebox/adapters/inbound/admin}/ui_pages/sonos.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/adapters/inbound/cli_controller.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/adapters/inbound/config.py +0 -0
- {gukebox-1.0.0.dev14/jukebox → gukebox-1.0.2/jukebox/adapters/outbound}/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/adapters/outbound/json_library_adapter.py +0 -0
- {gukebox-1.0.0.dev14/jukebox/adapters → gukebox-1.0.2/jukebox/adapters/outbound/players}/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/adapters/outbound/players/dryrun_player_adapter.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/adapters/outbound/players/sonos_player_adapter.py +0 -0
- {gukebox-1.0.0.dev14/jukebox/adapters/inbound → gukebox-1.0.2/jukebox/adapters/outbound/readers}/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/adapters/outbound/readers/dryrun_reader_adapter.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/adapters/outbound/readers/pn532_reader_adapter.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/adapters/outbound/sonos_discovery_adapter.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/adapters/outbound/text_current_tag_adapter.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/admin/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/admin/cli_presentation.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/admin/command_handlers.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/admin/commands.py +0 -0
- /gukebox-1.0.0.dev14/discstore/commands.py → /gukebox-1.0.2/jukebox/admin/library_commands.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/admin/pn532_command_handlers.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/admin/pn532_commands.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/admin/services.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/admin/sonos_households.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/app.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/di_container.py +0 -0
- {gukebox-1.0.0.dev14/jukebox/adapters/outbound → gukebox-1.0.2/jukebox/domain}/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/entities/current_tag_action.py +0 -0
- {gukebox-1.0.0.dev14/discstore → gukebox-1.0.2/jukebox}/domain/entities/current_tag_status.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/entities/disc.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/entities/library.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/entities/playback_action.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/entities/playback_session.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/entities/tag_event.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/errors.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/ports/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/ports/player_port.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/ports/reader_port.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/repositories/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/repositories/current_tag_repository.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/repositories/library_repository.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/use_cases/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/use_cases/determine_action.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/use_cases/determine_current_tag_action.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/domain/use_cases/handle_tag_event.py +0 -0
- {gukebox-1.0.0.dev14/jukebox/adapters/outbound/players → gukebox-1.0.2/jukebox/domain/use_cases/library}/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/pn532/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/pn532/profiles.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/definitions.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/dict_utils.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/entities.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/errors.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/file_settings_repository.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/migration.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/repositories.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/resolve.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/runtime_resolver.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/runtime_validation.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/selected_sonos_group_repository.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/service_protocols.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/timing_validation.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/types.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/validation_rules.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/settings/view_utils.py +0 -0
- {gukebox-1.0.0.dev14/jukebox/adapters/outbound/readers → gukebox-1.0.2/jukebox/shared}/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/shared/config_utils.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/shared/dependency_messages.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/shared/logger.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/shared/terminal_ui.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/shared/timing.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/sonos/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/sonos/discovery.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/sonos/selection.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/jukebox/sonos/service.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/pn532/__init__.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/pn532/pn532.py +0 -0
- {gukebox-1.0.0.dev14 → gukebox-1.0.2}/pn532/spi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: gukebox
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: A Jukebox to play music on speakers using 'CD' with NFC tag
|
|
5
5
|
Keywords: jukebox,music,nfc
|
|
6
6
|
Author: Gudsfile
|
|
@@ -43,7 +43,7 @@ Requires-Dist: spidev==3.8 ; extra == 'pn532'
|
|
|
43
43
|
Requires-Dist: lgpio==0.2.2.0 ; python_full_version < '3.13' and extra == 'pn532'
|
|
44
44
|
Requires-Dist: gukebox[api] ; extra == 'ui'
|
|
45
45
|
Requires-Dist: fastui==0.9.0 ; extra == 'ui'
|
|
46
|
-
Requires-Dist: python-multipart==0.0.
|
|
46
|
+
Requires-Dist: python-multipart==0.0.27 ; extra == 'ui'
|
|
47
47
|
Requires-Python: >=3.11, <3.14
|
|
48
48
|
Project-URL: Repository, https://github.com/Gudsfile/jukebox
|
|
49
49
|
Provides-Extra: api
|
|
@@ -3,19 +3,19 @@ from typing import Any
|
|
|
3
3
|
from fastapi import APIRouter, HTTPException, Response, status
|
|
4
4
|
from pydantic import ValidationError
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from jukebox.adapters.inbound.admin.api.models import (
|
|
7
7
|
CurrentTagDiscOutput,
|
|
8
8
|
CurrentTagStatusOutput,
|
|
9
9
|
DiscInput,
|
|
10
10
|
DiscOutput,
|
|
11
11
|
DiscPatchInput,
|
|
12
12
|
)
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
13
|
+
from jukebox.domain.entities import CurrentTagStatus, Disc, DiscMetadata, DiscOption
|
|
14
|
+
from jukebox.domain.use_cases.library.add_disc import AddDisc
|
|
15
|
+
from jukebox.domain.use_cases.library.edit_disc import EditDisc
|
|
16
|
+
from jukebox.domain.use_cases.library.get_current_tag_status import GetCurrentTagStatus
|
|
17
|
+
from jukebox.domain.use_cases.library.get_disc import GetDisc
|
|
18
|
+
from jukebox.domain.use_cases.library.remove_disc import RemoveDisc
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
def build_current_tag_router(
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
from fastapi import APIRouter, HTTPException, Response, status
|
|
2
2
|
from pydantic import ValidationError
|
|
3
3
|
|
|
4
|
-
from
|
|
5
|
-
from
|
|
6
|
-
from
|
|
7
|
-
from
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from
|
|
4
|
+
from jukebox.adapters.inbound.admin.api.models import DiscInput, DiscOutput, DiscPatchInput
|
|
5
|
+
from jukebox.domain.entities import Disc, DiscMetadata, DiscOption
|
|
6
|
+
from jukebox.domain.use_cases.library.add_disc import AddDisc
|
|
7
|
+
from jukebox.domain.use_cases.library.edit_disc import EditDisc
|
|
8
|
+
from jukebox.domain.use_cases.library.get_disc import GetDisc
|
|
9
|
+
from jukebox.domain.use_cases.library.list_discs import ListDiscs
|
|
10
|
+
from jukebox.domain.use_cases.library.remove_disc import RemoveDisc
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def build_discs_router(
|
|
@@ -2,7 +2,7 @@ from typing import Any, cast
|
|
|
2
2
|
|
|
3
3
|
from fastapi import APIRouter, HTTPException
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from jukebox.adapters.inbound.admin.api.models import SettingsPatchInput, SettingsResetInput
|
|
6
6
|
from jukebox.settings.errors import SettingsError
|
|
7
7
|
from jukebox.settings.service_protocols import SettingsService
|
|
8
8
|
from jukebox.settings.types import JsonObject
|
|
@@ -5,9 +5,9 @@ from jukebox.shared.dependency_messages import optional_extra_dependency_message
|
|
|
5
5
|
try:
|
|
6
6
|
from fastapi import FastAPI, HTTPException
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from
|
|
8
|
+
from jukebox.adapters.inbound.admin.api.current_tag_router import build_current_tag_router
|
|
9
|
+
from jukebox.adapters.inbound.admin.api.discs_router import build_discs_router
|
|
10
|
+
from jukebox.adapters.inbound.admin.api.models import (
|
|
11
11
|
CurrentTagDiscOutput,
|
|
12
12
|
CurrentTagStatusOutput,
|
|
13
13
|
DiscInput,
|
|
@@ -16,19 +16,19 @@ try:
|
|
|
16
16
|
SettingsPatchInput,
|
|
17
17
|
SettingsResetInput,
|
|
18
18
|
)
|
|
19
|
-
from
|
|
19
|
+
from jukebox.adapters.inbound.admin.api.settings_router import build_settings_router
|
|
20
20
|
except ModuleNotFoundError as e:
|
|
21
21
|
if e.name != "fastapi":
|
|
22
22
|
raise
|
|
23
23
|
raise ModuleNotFoundError(
|
|
24
24
|
optional_extra_dependency_message("The `api_controller` module", "api", "jukebox-admin api")
|
|
25
25
|
) from e
|
|
26
|
-
from
|
|
27
|
-
from
|
|
28
|
-
from
|
|
29
|
-
from
|
|
30
|
-
from
|
|
31
|
-
from
|
|
26
|
+
from jukebox.domain.use_cases.library.add_disc import AddDisc
|
|
27
|
+
from jukebox.domain.use_cases.library.edit_disc import EditDisc
|
|
28
|
+
from jukebox.domain.use_cases.library.get_current_tag_status import GetCurrentTagStatus
|
|
29
|
+
from jukebox.domain.use_cases.library.get_disc import GetDisc
|
|
30
|
+
from jukebox.domain.use_cases.library.list_discs import ListDiscs
|
|
31
|
+
from jukebox.domain.use_cases.library.remove_disc import RemoveDisc
|
|
32
32
|
from jukebox.settings.entities import SelectedSonosGroupSettings
|
|
33
33
|
from jukebox.settings.selected_sonos_group_repository import SettingsSelectedSonosGroupRepository
|
|
34
34
|
from jukebox.settings.service_protocols import SettingsService
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from
|
|
3
|
+
from jukebox.adapters.inbound.admin.cli_display import display_library_line, display_library_table
|
|
4
|
+
from jukebox.admin.library_commands import (
|
|
5
5
|
CliAddCommand,
|
|
6
6
|
CliEditCommand,
|
|
7
7
|
CliGetCommand,
|
|
@@ -9,14 +9,14 @@ from discstore.commands import (
|
|
|
9
9
|
CliRemoveCommand,
|
|
10
10
|
CliSearchCommand,
|
|
11
11
|
)
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from
|
|
12
|
+
from jukebox.domain.entities import Disc, DiscMetadata, DiscOption
|
|
13
|
+
from jukebox.domain.use_cases.library.add_disc import AddDisc
|
|
14
|
+
from jukebox.domain.use_cases.library.edit_disc import EditDisc
|
|
15
|
+
from jukebox.domain.use_cases.library.get_disc import GetDisc
|
|
16
|
+
from jukebox.domain.use_cases.library.list_discs import ListDiscs
|
|
17
|
+
from jukebox.domain.use_cases.library.remove_disc import RemoveDisc
|
|
18
|
+
from jukebox.domain.use_cases.library.resolve_tag_id import ResolveTagId
|
|
19
|
+
from jukebox.domain.use_cases.library.search_discs import SearchDiscs
|
|
20
20
|
|
|
21
21
|
LOGGER = logging.getLogger("discstore")
|
|
22
22
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from
|
|
5
|
-
from
|
|
6
|
-
from
|
|
7
|
-
from
|
|
8
|
-
from
|
|
9
|
-
from
|
|
3
|
+
from jukebox.adapters.inbound.admin.cli_display import display_library_line, display_library_table
|
|
4
|
+
from jukebox.domain.entities import CurrentTagStatus, Disc, DiscMetadata, DiscOption
|
|
5
|
+
from jukebox.domain.use_cases.library.add_disc import AddDisc
|
|
6
|
+
from jukebox.domain.use_cases.library.edit_disc import EditDisc
|
|
7
|
+
from jukebox.domain.use_cases.library.get_current_tag_status import GetCurrentTagStatus
|
|
8
|
+
from jukebox.domain.use_cases.library.list_discs import ListDiscs
|
|
9
|
+
from jukebox.domain.use_cases.library.remove_disc import RemoveDisc
|
|
10
10
|
|
|
11
11
|
LOGGER = logging.getLogger("discstore")
|
|
12
12
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from collections.abc import AsyncIterator
|
|
2
1
|
from typing import Annotated
|
|
3
2
|
|
|
4
3
|
from jukebox.shared.dependency_messages import optional_extra_dependency_message
|
|
@@ -17,25 +16,21 @@ except ModuleNotFoundError as e:
|
|
|
17
16
|
|
|
18
17
|
from pydantic import BaseModel, Field
|
|
19
18
|
|
|
20
|
-
from
|
|
21
|
-
from
|
|
22
|
-
from
|
|
23
|
-
from
|
|
24
|
-
from
|
|
25
|
-
from
|
|
26
|
-
from
|
|
27
|
-
from
|
|
28
|
-
from
|
|
29
|
-
from
|
|
30
|
-
from
|
|
31
|
-
from jukebox.settings.definitions import
|
|
32
|
-
EditableSettingDisplay,
|
|
33
|
-
get_setting_definition,
|
|
34
|
-
)
|
|
19
|
+
from jukebox.adapters.inbound.admin.api_controller import APIController
|
|
20
|
+
from jukebox.adapters.inbound.admin.ui_pages.library import DiscForm, LibraryUIPageBuilder
|
|
21
|
+
from jukebox.adapters.inbound.admin.ui_pages.settings import SettingsUIPageBuilder
|
|
22
|
+
from jukebox.adapters.inbound.admin.ui_pages.sonos import SonosSelectionForm, SonosUIPageBuilder
|
|
23
|
+
from jukebox.domain.entities import Disc, DiscMetadata, DiscOption
|
|
24
|
+
from jukebox.domain.use_cases.library.add_disc import AddDisc
|
|
25
|
+
from jukebox.domain.use_cases.library.edit_disc import EditDisc
|
|
26
|
+
from jukebox.domain.use_cases.library.get_current_tag_status import GetCurrentTagStatus
|
|
27
|
+
from jukebox.domain.use_cases.library.get_disc import GetDisc
|
|
28
|
+
from jukebox.domain.use_cases.library.list_discs import ListDiscs
|
|
29
|
+
from jukebox.domain.use_cases.library.remove_disc import RemoveDisc
|
|
30
|
+
from jukebox.settings.definitions import get_setting_definition
|
|
35
31
|
from jukebox.settings.errors import SettingsError
|
|
36
32
|
from jukebox.settings.selected_sonos_group_repository import SettingsSelectedSonosGroupRepository
|
|
37
33
|
from jukebox.settings.service_protocols import SettingsService
|
|
38
|
-
from jukebox.settings.types import JsonObject, JsonValue
|
|
39
34
|
from jukebox.sonos.discovery import SonosDiscoveryError
|
|
40
35
|
from jukebox.sonos.selection import SaveSonosSelection
|
|
41
36
|
from jukebox.sonos.service import SonosService
|
|
@@ -81,12 +76,12 @@ class UIController(APIController):
|
|
|
81
76
|
|
|
82
77
|
@self.app.get("/api/ui/", response_model=FastUI, response_model_exclude_none=True)
|
|
83
78
|
def list_discs(toast: str | None = None) -> list[AnyComponent]:
|
|
84
|
-
return self.
|
|
79
|
+
return self.library_pages.build_index_page_components(toast=toast)
|
|
85
80
|
|
|
86
81
|
@self.app.get("/api/ui/current-tag-banner/events")
|
|
87
82
|
async def get_current_tag_banner_events(request: Request) -> StreamingResponse:
|
|
88
83
|
return StreamingResponse(
|
|
89
|
-
self.
|
|
84
|
+
self.library_pages.current_tag_banner_event_stream(request),
|
|
90
85
|
media_type="text/event-stream",
|
|
91
86
|
headers={
|
|
92
87
|
"Cache-Control": "no-cache",
|
|
@@ -97,9 +92,11 @@ class UIController(APIController):
|
|
|
97
92
|
|
|
98
93
|
@self.app.get("/api/ui/discs/new", response_model=FastUI, response_model_exclude_none=True)
|
|
99
94
|
def new_disc_form(prefill: str | None = None) -> list[AnyComponent]:
|
|
100
|
-
return self.
|
|
95
|
+
return self.library_pages.build_form_page_components(
|
|
101
96
|
title="Add disc",
|
|
102
|
-
form_components=self.
|
|
97
|
+
form_components=self.library_pages.build_new_disc_form_components(
|
|
98
|
+
prefill_current=(prefill == "current")
|
|
99
|
+
),
|
|
103
100
|
)
|
|
104
101
|
|
|
105
102
|
@self.app.post("/api/ui/discs", response_model=FastUI, response_model_exclude_none=True)
|
|
@@ -124,9 +121,9 @@ class UIController(APIController):
|
|
|
124
121
|
|
|
125
122
|
@self.app.get("/api/ui/discs/{tag_id}/edit", response_model=FastUI, response_model_exclude_none=True)
|
|
126
123
|
def edit_disc_form(tag_id: str) -> list[AnyComponent]:
|
|
127
|
-
return self.
|
|
124
|
+
return self.library_pages.build_form_page_components(
|
|
128
125
|
title=f"Edit disc {tag_id}",
|
|
129
|
-
form_components=self.
|
|
126
|
+
form_components=self.library_pages.build_edit_disc_form_components(tag_id),
|
|
130
127
|
)
|
|
131
128
|
|
|
132
129
|
@self.app.post("/api/ui/discs/{tag_id}", response_model=FastUI, response_model_exclude_none=True)
|
|
@@ -166,9 +163,9 @@ class UIController(APIController):
|
|
|
166
163
|
|
|
167
164
|
@self.app.get("/api/ui/discs/{tag_id}/delete", response_model=FastUI, response_model_exclude_none=True)
|
|
168
165
|
def delete_disc_confirmation(tag_id: str) -> list[AnyComponent]:
|
|
169
|
-
return self.
|
|
166
|
+
return self.library_pages.build_form_page_components(
|
|
170
167
|
title=f"Delete disc {tag_id}",
|
|
171
|
-
form_components=self.
|
|
168
|
+
form_components=self.library_pages.build_delete_disc_form_components(tag_id),
|
|
172
169
|
)
|
|
173
170
|
|
|
174
171
|
# Fast-UI buttons and forms do not support the DELETE method directly. So we cannot call DELETE on
|
|
@@ -186,11 +183,11 @@ class UIController(APIController):
|
|
|
186
183
|
|
|
187
184
|
@self.app.get("/api/ui/settings", response_model=FastUI, response_model_exclude_none=True)
|
|
188
185
|
def settings_page(toast: str | None = None, toast_message: str | None = None) -> list[AnyComponent]:
|
|
189
|
-
return self.
|
|
186
|
+
return self.settings_pages.build_settings_page_components(toast=toast, toast_message=toast_message)
|
|
190
187
|
|
|
191
188
|
@self.app.get("/api/ui/settings/{setting_path}/edit", response_model=FastUI, response_model_exclude_none=True)
|
|
192
189
|
def edit_setting_form(setting_path: str) -> list[AnyComponent]:
|
|
193
|
-
return self.
|
|
190
|
+
return self.settings_pages.build_settings_edit_page_components(setting_path)
|
|
194
191
|
|
|
195
192
|
@self.app.post("/api/ui/settings/{setting_path}", response_model=FastUI, response_model_exclude_none=True)
|
|
196
193
|
async def update_setting(
|
|
@@ -202,13 +199,15 @@ class UIController(APIController):
|
|
|
202
199
|
raise HTTPException(status_code=404, detail=f"Unknown setting path: {setting_path}")
|
|
203
200
|
|
|
204
201
|
try:
|
|
205
|
-
patch = self.
|
|
202
|
+
patch = self.settings_pages.build_settings_patch(setting_path, form.value)
|
|
206
203
|
result = self.settings_service.patch_persisted_settings(patch)
|
|
207
204
|
except ValueError as err:
|
|
208
205
|
raise self._field_validation_error("value", str(err))
|
|
209
206
|
except SettingsError as err:
|
|
210
|
-
if self.
|
|
211
|
-
|
|
207
|
+
if self.settings_pages.persisted_value_matches(
|
|
208
|
+
setting_path, self.settings_pages.lookup_optional_dotted_path(patch, setting_path)
|
|
209
|
+
):
|
|
210
|
+
return self.settings_pages.build_settings_success_response(
|
|
212
211
|
"Settings saved, but effective settings are still unavailable."
|
|
213
212
|
)
|
|
214
213
|
raise self._field_validation_error("value", str(err))
|
|
@@ -217,15 +216,15 @@ class UIController(APIController):
|
|
|
217
216
|
except Exception as err:
|
|
218
217
|
raise HTTPException(status_code=500, detail=f"Server error: {str(err)}")
|
|
219
218
|
|
|
220
|
-
return self.
|
|
219
|
+
return self.settings_pages.build_settings_success_response(str(result["message"]))
|
|
221
220
|
|
|
222
221
|
@self.app.post("/api/ui/settings/{setting_path}/reset", response_model=FastUI, response_model_exclude_none=True)
|
|
223
222
|
async def reset_setting(setting_path: str) -> list[AnyComponent]:
|
|
224
|
-
return self.
|
|
223
|
+
return self.settings_pages.reset_setting(setting_path)
|
|
225
224
|
|
|
226
225
|
@self.app.get("/api/ui/sonos", response_model=FastUI, response_model_exclude_none=True)
|
|
227
226
|
def sonos_page(toast: str | None = None, toast_message: str | None = None) -> list[AnyComponent]:
|
|
228
|
-
return self.
|
|
227
|
+
return self.sonos_pages.build_sonos_page_components(toast=toast, toast_message=toast_message)
|
|
229
228
|
|
|
230
229
|
@self.app.get("/api/ui/sonos/edit", response_model=FastUI, response_model_exclude_none=True)
|
|
231
230
|
def edit_sonos_form(
|
|
@@ -236,7 +235,7 @@ class UIController(APIController):
|
|
|
236
235
|
field_errors = None
|
|
237
236
|
if error_message:
|
|
238
237
|
field_errors = {self._sonos_field_name_for_error(error_message): error_message}
|
|
239
|
-
return self.
|
|
238
|
+
return self.sonos_pages.build_sonos_edit_page_components(
|
|
240
239
|
error_message=error_message,
|
|
241
240
|
field_errors=field_errors,
|
|
242
241
|
submitted_uids=uids,
|
|
@@ -292,38 +291,6 @@ class UIController(APIController):
|
|
|
292
291
|
c.FireEvent(event=GoToEvent(url=f"/?toast={toast_event_name}")),
|
|
293
292
|
]
|
|
294
293
|
|
|
295
|
-
def _build_settings_success_response(self, message: str) -> list[AnyComponent]:
|
|
296
|
-
return self.settings_pages.build_settings_success_response(message)
|
|
297
|
-
|
|
298
|
-
def _reset_setting(self, setting_path: str) -> list[AnyComponent]:
|
|
299
|
-
return self.settings_pages.reset_setting(setting_path)
|
|
300
|
-
|
|
301
|
-
def _build_sonos_page_components(
|
|
302
|
-
self,
|
|
303
|
-
toast: str | None = None,
|
|
304
|
-
toast_message: str | None = None,
|
|
305
|
-
error_message: str | None = None,
|
|
306
|
-
) -> list[AnyComponent]:
|
|
307
|
-
return self.sonos_pages.build_sonos_page_components(
|
|
308
|
-
toast=toast,
|
|
309
|
-
toast_message=toast_message,
|
|
310
|
-
error_message=error_message,
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
def _build_sonos_edit_page_components(
|
|
314
|
-
self,
|
|
315
|
-
error_message: str | None = None,
|
|
316
|
-
field_errors: dict[str, str] | None = None,
|
|
317
|
-
submitted_uids: list[str] | None = None,
|
|
318
|
-
submitted_coordinator_uid: str | None = None,
|
|
319
|
-
) -> list[AnyComponent]:
|
|
320
|
-
return self.sonos_pages.build_sonos_edit_page_components(
|
|
321
|
-
error_message=error_message,
|
|
322
|
-
field_errors=field_errors,
|
|
323
|
-
submitted_uids=submitted_uids,
|
|
324
|
-
submitted_coordinator_uid=submitted_coordinator_uid,
|
|
325
|
-
)
|
|
326
|
-
|
|
327
294
|
def _reset_sonos_selection(self) -> list[AnyComponent]:
|
|
328
295
|
selected_group_repository = SettingsSelectedSonosGroupRepository(self.settings_service)
|
|
329
296
|
try:
|
|
@@ -333,7 +300,7 @@ class UIController(APIController):
|
|
|
333
300
|
return self.sonos_pages.build_sonos_success_response(
|
|
334
301
|
"Sonos selection cleared, but effective settings are still unavailable."
|
|
335
302
|
)
|
|
336
|
-
return self.
|
|
303
|
+
return self.sonos_pages.build_sonos_page_components(error_message=str(err))
|
|
337
304
|
except HTTPException:
|
|
338
305
|
raise
|
|
339
306
|
except Exception as err:
|
|
@@ -372,116 +339,6 @@ class UIController(APIController):
|
|
|
372
339
|
|
|
373
340
|
return f"{prefix}{speaker.name} [{speaker.uid}]"
|
|
374
341
|
|
|
375
|
-
def _build_index_page_components(self, toast: str | None = None) -> list[AnyComponent]:
|
|
376
|
-
return self.library_pages.build_index_page_components(toast=toast)
|
|
377
|
-
|
|
378
|
-
def _build_settings_page_components(
|
|
379
|
-
self,
|
|
380
|
-
toast: str | None = None,
|
|
381
|
-
toast_message: str | None = None,
|
|
382
|
-
) -> list[AnyComponent]:
|
|
383
|
-
return self.settings_pages.build_settings_page_components(toast=toast, toast_message=toast_message)
|
|
384
|
-
|
|
385
|
-
def _build_settings_section_components(
|
|
386
|
-
self,
|
|
387
|
-
section: str,
|
|
388
|
-
settings: list[EditableSettingDisplay],
|
|
389
|
-
) -> list[AnyComponent]:
|
|
390
|
-
return self.settings_pages.build_settings_section_components(section, settings)
|
|
391
|
-
|
|
392
|
-
def _build_settings_row(self, setting: EditableSettingDisplay, index: int) -> AnyComponent:
|
|
393
|
-
return self.settings_pages.build_settings_row(setting, index)
|
|
394
|
-
|
|
395
|
-
def _build_settings_edit_page_components(
|
|
396
|
-
self,
|
|
397
|
-
setting_path: str,
|
|
398
|
-
reset_error: str | None = None,
|
|
399
|
-
) -> list[AnyComponent]:
|
|
400
|
-
return self.settings_pages.build_settings_edit_page_components(setting_path, reset_error=reset_error)
|
|
401
|
-
|
|
402
|
-
def _build_settings_edit_form(self, setting: EditableSettingDisplay) -> AnyComponent:
|
|
403
|
-
return self.settings_pages.build_settings_edit_form(setting)
|
|
404
|
-
|
|
405
|
-
def _build_settings_reset_form(self, setting_path: str) -> AnyComponent:
|
|
406
|
-
return self.settings_pages.build_settings_reset_form(setting_path)
|
|
407
|
-
|
|
408
|
-
def _get_settings_displays(self) -> tuple[list[EditableSettingDisplay], str | None]:
|
|
409
|
-
return self.settings_pages.get_settings_displays()
|
|
410
|
-
|
|
411
|
-
def _build_settings_badges(self, setting: EditableSettingDisplay) -> list[AnyComponent]:
|
|
412
|
-
return self.settings_pages.build_settings_badges(setting)
|
|
413
|
-
|
|
414
|
-
def _build_settings_value_summary(self, setting: EditableSettingDisplay) -> AnyComponent:
|
|
415
|
-
return self.settings_pages.build_settings_value_summary(setting)
|
|
416
|
-
|
|
417
|
-
def _build_settings_value_cell(self, label: str, value: str) -> AnyComponent:
|
|
418
|
-
return self.settings_pages.build_settings_value_cell(label, value)
|
|
419
|
-
|
|
420
|
-
def _build_settings_edit_guidance(self, setting: EditableSettingDisplay) -> str:
|
|
421
|
-
return self.settings_pages.build_settings_edit_guidance(setting)
|
|
422
|
-
|
|
423
|
-
def _build_settings_patch(self, setting_path: str, raw_value: str) -> JsonObject:
|
|
424
|
-
return self.settings_pages.build_settings_patch(setting_path, raw_value)
|
|
425
|
-
|
|
426
|
-
def _build_dotted_patch(self, dotted_path: str, value: JsonValue) -> JsonObject:
|
|
427
|
-
return self.settings_pages.build_dotted_patch(dotted_path, value)
|
|
428
|
-
|
|
429
|
-
def _persisted_value_matches(self, dotted_path: str, expected_value: object) -> bool:
|
|
430
|
-
return self.settings_pages.persisted_value_matches(dotted_path, expected_value)
|
|
431
|
-
|
|
432
|
-
def _has_persisted_value(self, dotted_path: str) -> bool:
|
|
433
|
-
return self.settings_pages.has_persisted_value(dotted_path)
|
|
434
|
-
|
|
435
|
-
def _lookup_optional_dotted_path(self, root: JsonObject, dotted_path: str) -> object:
|
|
436
|
-
return self.settings_pages.lookup_optional_dotted_path(root, dotted_path)
|
|
437
|
-
|
|
438
|
-
def _format_settings_display_value(self, setting_path: str, value: object) -> str:
|
|
439
|
-
return self.settings_pages.format_settings_display_value(setting_path, value)
|
|
440
|
-
|
|
441
|
-
def _format_settings_provenance(self, provenance: str) -> str:
|
|
442
|
-
return self.settings_pages.format_settings_provenance(provenance)
|
|
443
|
-
|
|
444
|
-
def _build_form_page_components(self, title: str, form_components: list[AnyComponent]) -> list[AnyComponent]:
|
|
445
|
-
return self.library_pages.build_form_page_components(title=title, form_components=form_components)
|
|
446
|
-
|
|
447
|
-
def _build_current_tag_banner_components(self, current_tag_status: CurrentTagStatus | None) -> list[AnyComponent]:
|
|
448
|
-
return self.library_pages.build_current_tag_banner_components(current_tag_status)
|
|
449
|
-
|
|
450
|
-
def _build_disc_library_components(self, discs: list[DiscTable]) -> list[AnyComponent]:
|
|
451
|
-
return self.library_pages.build_disc_library_components(discs)
|
|
452
|
-
|
|
453
|
-
def _build_disc_library_header(self) -> AnyComponent:
|
|
454
|
-
return self.library_pages._build_disc_library_header()
|
|
455
|
-
|
|
456
|
-
def _build_disc_library_row(self, disc: DiscTable) -> AnyComponent:
|
|
457
|
-
return self.library_pages._build_disc_library_row(disc)
|
|
458
|
-
|
|
459
|
-
def _build_disc_header_cell(self, label: str, class_name: str) -> AnyComponent:
|
|
460
|
-
return self.library_pages._build_disc_header_cell(label, class_name)
|
|
461
|
-
|
|
462
|
-
def _build_disc_value_cell(self, label: str, value: str | None, class_name: str) -> AnyComponent:
|
|
463
|
-
return self.library_pages._build_disc_value_cell(label, value, class_name)
|
|
464
|
-
|
|
465
|
-
def _build_new_disc_form_components(self, prefill_current: bool) -> list[AnyComponent]:
|
|
466
|
-
return self.library_pages.build_new_disc_form_components(prefill_current)
|
|
467
|
-
|
|
468
|
-
def _build_edit_disc_form_components(self, tag_id: str) -> list[AnyComponent]:
|
|
469
|
-
return self.library_pages.build_edit_disc_form_components(tag_id)
|
|
470
|
-
|
|
471
|
-
def _build_delete_disc_form_components(self, tag_id: str) -> list[AnyComponent]:
|
|
472
|
-
return self.library_pages.build_delete_disc_form_components(tag_id)
|
|
473
|
-
|
|
474
|
-
async def _current_tag_banner_event_stream(
|
|
475
|
-
self,
|
|
476
|
-
request: Request,
|
|
477
|
-
poll_interval_seconds: float = 0.5,
|
|
478
|
-
) -> AsyncIterator[bytes]:
|
|
479
|
-
async for payload in self.library_pages.current_tag_banner_event_stream(request, poll_interval_seconds):
|
|
480
|
-
yield payload
|
|
481
|
-
|
|
482
|
-
def _serialize_current_tag_components(self, components: list[AnyComponent]) -> str:
|
|
483
|
-
return self.library_pages.serialize_current_tag_components(components)
|
|
484
|
-
|
|
485
342
|
@staticmethod
|
|
486
343
|
def _sonos_field_name_for_error(message: str) -> str:
|
|
487
344
|
if "coordinator" in message:
|
|
@@ -8,10 +8,10 @@ from fastui import components as c
|
|
|
8
8
|
from fastui.events import BackEvent, GoToEvent, PageEvent
|
|
9
9
|
from pydantic import BaseModel, Field
|
|
10
10
|
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
11
|
+
from jukebox.domain.entities import CurrentTagStatus, DiscMetadata, DiscOption
|
|
12
|
+
from jukebox.domain.use_cases.library.get_current_tag_status import GetCurrentTagStatus
|
|
13
|
+
from jukebox.domain.use_cases.library.get_disc import GetDisc
|
|
14
|
+
from jukebox.domain.use_cases.library.list_discs import ListDiscs
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class DiscTable(DiscMetadata, DiscOption):
|
|
@@ -5,8 +5,8 @@ from typing import Annotated
|
|
|
5
5
|
import typer
|
|
6
6
|
from pydantic import ValidationError
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from
|
|
8
|
+
from jukebox.admin.library_command_handlers import execute_library_command
|
|
9
|
+
from jukebox.admin.library_commands import (
|
|
10
10
|
CliAddCommand,
|
|
11
11
|
CliEditCommand,
|
|
12
12
|
CliGetCommand,
|
|
@@ -16,7 +16,6 @@ from discstore.commands import (
|
|
|
16
16
|
CliSearchCommand,
|
|
17
17
|
InteractiveCliCommand,
|
|
18
18
|
)
|
|
19
|
-
from discstore.di_container import build_cli_controller, build_interactive_cli_controller
|
|
20
19
|
from jukebox.settings.errors import SettingsError
|
|
21
20
|
from jukebox.shared.config_utils import get_package_version
|
|
22
21
|
from jukebox.shared.logger import set_logger
|
|
@@ -41,7 +40,14 @@ from .commands import (
|
|
|
41
40
|
is_settings_command,
|
|
42
41
|
is_sonos_command,
|
|
43
42
|
)
|
|
44
|
-
from .di_container import
|
|
43
|
+
from .di_container import (
|
|
44
|
+
build_admin_api_app,
|
|
45
|
+
build_admin_services,
|
|
46
|
+
build_admin_ui_app,
|
|
47
|
+
build_cli_controller,
|
|
48
|
+
build_interactive_cli_controller,
|
|
49
|
+
build_settings_service,
|
|
50
|
+
)
|
|
45
51
|
from .pn532_command_handlers import execute_pn532_command
|
|
46
52
|
from .pn532_commands import Pn532ProbeCommand, Pn532ProfilesCommand, Pn532SelectCommand, is_pn532_command
|
|
47
53
|
from .sonos_households import GroupedSonosHousehold
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
from
|
|
2
|
-
from discstore.adapters.outbound.text_current_tag_adapter import TextCurrentTagAdapter
|
|
3
|
-
from discstore.domain.use_cases.add_disc import AddDisc
|
|
4
|
-
from discstore.domain.use_cases.edit_disc import EditDisc
|
|
5
|
-
from discstore.domain.use_cases.get_current_tag_status import GetCurrentTagStatus
|
|
6
|
-
from discstore.domain.use_cases.get_disc import GetDisc
|
|
7
|
-
from discstore.domain.use_cases.list_discs import ListDiscs
|
|
8
|
-
from discstore.domain.use_cases.remove_disc import RemoveDisc
|
|
1
|
+
from jukebox.adapters.outbound.json_library_adapter import JsonLibraryAdapter
|
|
9
2
|
from jukebox.adapters.outbound.sonos_discovery_adapter import SoCoSonosDiscoveryAdapter
|
|
3
|
+
from jukebox.adapters.outbound.text_current_tag_adapter import TextCurrentTagAdapter
|
|
4
|
+
from jukebox.domain.use_cases.library.add_disc import AddDisc
|
|
5
|
+
from jukebox.domain.use_cases.library.edit_disc import EditDisc
|
|
6
|
+
from jukebox.domain.use_cases.library.get_current_tag_status import GetCurrentTagStatus
|
|
7
|
+
from jukebox.domain.use_cases.library.get_disc import GetDisc
|
|
8
|
+
from jukebox.domain.use_cases.library.list_discs import ListDiscs
|
|
9
|
+
from jukebox.domain.use_cases.library.remove_disc import RemoveDisc
|
|
10
|
+
from jukebox.domain.use_cases.library.resolve_tag_id import ResolveTagId
|
|
11
|
+
from jukebox.domain.use_cases.library.search_discs import SearchDiscs
|
|
10
12
|
from jukebox.settings.file_settings_repository import FileSettingsRepository
|
|
11
13
|
from jukebox.settings.resolve import SettingsService as SettingsServiceImpl
|
|
12
14
|
from jukebox.settings.resolve import build_environment_settings_overrides
|
|
@@ -56,7 +58,7 @@ def build_admin_api_app(library_path: str, services: AdminServices):
|
|
|
56
58
|
repository = JsonLibraryAdapter(library_path)
|
|
57
59
|
current_tag_repository = TextCurrentTagAdapter(get_current_tag_path(library_path))
|
|
58
60
|
|
|
59
|
-
from
|
|
61
|
+
from jukebox.adapters.inbound.admin.api_controller import APIController
|
|
60
62
|
|
|
61
63
|
return APIController(
|
|
62
64
|
AddDisc(repository),
|
|
@@ -74,7 +76,7 @@ def build_admin_ui_app(library_path: str, services: AdminServices):
|
|
|
74
76
|
repository = JsonLibraryAdapter(library_path)
|
|
75
77
|
current_tag_repository = TextCurrentTagAdapter(get_current_tag_path(library_path))
|
|
76
78
|
|
|
77
|
-
from
|
|
79
|
+
from jukebox.adapters.inbound.admin.ui_controller import UIController
|
|
78
80
|
|
|
79
81
|
return UIController(
|
|
80
82
|
AddDisc(repository),
|
|
@@ -90,3 +92,36 @@ def build_admin_ui_app(library_path: str, services: AdminServices):
|
|
|
90
92
|
|
|
91
93
|
def build_sonos_service() -> SonosService:
|
|
92
94
|
return DefaultSonosService(SoCoSonosDiscoveryAdapter())
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def build_cli_controller(library_path: str):
|
|
98
|
+
repository = JsonLibraryAdapter(library_path)
|
|
99
|
+
current_tag_repository = TextCurrentTagAdapter(get_current_tag_path(library_path))
|
|
100
|
+
get_current_tag_status = GetCurrentTagStatus(current_tag_repository, repository)
|
|
101
|
+
|
|
102
|
+
from jukebox.adapters.inbound.admin.cli_controller import CLIController
|
|
103
|
+
|
|
104
|
+
return CLIController(
|
|
105
|
+
AddDisc(repository),
|
|
106
|
+
ListDiscs(repository),
|
|
107
|
+
RemoveDisc(repository),
|
|
108
|
+
EditDisc(repository),
|
|
109
|
+
GetDisc(repository),
|
|
110
|
+
SearchDiscs(repository),
|
|
111
|
+
ResolveTagId(get_current_tag_status),
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def build_interactive_cli_controller(library_path: str):
|
|
116
|
+
repository = JsonLibraryAdapter(library_path)
|
|
117
|
+
current_tag_repository = TextCurrentTagAdapter(get_current_tag_path(library_path))
|
|
118
|
+
|
|
119
|
+
from jukebox.adapters.inbound.admin.interactive_cli_controller import InteractiveCLIController
|
|
120
|
+
|
|
121
|
+
return InteractiveCLIController(
|
|
122
|
+
AddDisc(repository),
|
|
123
|
+
ListDiscs(repository),
|
|
124
|
+
RemoveDisc(repository),
|
|
125
|
+
EditDisc(repository),
|
|
126
|
+
GetCurrentTagStatus(current_tag_repository, repository),
|
|
127
|
+
)
|