0f25ebc26d
* plex integration * The big one - Full Music Source page rework + Playlist importing + Full Plex Integration + Discovery Options + More Like This/Surprise Me/Instant Mix + More... * Music source track page - Play all / shuffle fixes * lint * format * fix type checks * format
72 lines
2.5 KiB
Python
72 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from fastapi.responses import Response, StreamingResponse
|
|
|
|
from infrastructure.cache.memory_cache import CacheInterface
|
|
from repositories.plex_models import StreamProxyResult
|
|
from repositories.protocols.plex import PlexRepositoryProtocol
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class PlexPlaybackService:
|
|
def __init__(
|
|
self,
|
|
plex_repo: PlexRepositoryProtocol,
|
|
cache: CacheInterface | None = None,
|
|
) -> None:
|
|
self._plex = plex_repo
|
|
self._cache = cache
|
|
|
|
async def proxy_head(self, part_key: str) -> Response:
|
|
result: StreamProxyResult = await self._plex.proxy_head_stream(part_key)
|
|
return Response(status_code=result.status_code, headers=result.headers)
|
|
|
|
async def proxy_stream(
|
|
self, part_key: str, range_header: str | None = None
|
|
) -> StreamingResponse:
|
|
result: StreamProxyResult = await self._plex.proxy_get_stream(
|
|
part_key, range_header=range_header
|
|
)
|
|
return StreamingResponse(
|
|
content=result.body_chunks,
|
|
status_code=result.status_code,
|
|
headers=result.headers,
|
|
media_type=result.media_type,
|
|
)
|
|
|
|
async def scrobble(self, rating_key: str) -> bool:
|
|
try:
|
|
ok = await self._plex.scrobble(rating_key)
|
|
if self._cache:
|
|
await self._cache.delete("plex:sessions")
|
|
return ok
|
|
except Exception: # noqa: BLE001
|
|
logger.warning("Plex scrobble failed for %s", rating_key, exc_info=True)
|
|
return False
|
|
|
|
async def report_now_playing(self, rating_key: str) -> bool:
|
|
try:
|
|
ok = await self._plex.now_playing(rating_key)
|
|
if self._cache:
|
|
await self._cache.delete("plex:sessions")
|
|
return ok
|
|
except Exception: # noqa: BLE001
|
|
logger.warning("Plex now-playing failed for %s", rating_key, exc_info=True)
|
|
return False
|
|
|
|
async def report_stopped(self, rating_key: str) -> bool:
|
|
try:
|
|
ok = await self._plex.now_playing(rating_key, state="stopped")
|
|
if self._cache:
|
|
await self._cache.delete("plex:sessions")
|
|
return ok
|
|
except Exception: # noqa: BLE001
|
|
logger.warning("Plex stopped report failed for %s", rating_key, exc_info=True)
|
|
return False
|
|
|
|
async def proxy_thumb(self, rating_key: str, size: int = 500) -> tuple[bytes, str]:
|
|
return await self._plex.proxy_thumb(rating_key, size=size)
|