Added is_valid check to sources. Filebased entries are valid, iff they appear in index.

This commit is contained in:
Christoph Stahl 2025-02-15 01:32:13 +01:00
parent 9232f3870f
commit c381133252
3 changed files with 80 additions and 27 deletions

View file

@ -32,6 +32,8 @@ import socketio
from aiohttp import web
from profanity_check import predict
from syng.sources.source import EntryNotValid
from .result import Result
from . import jsonencoder
@ -314,18 +316,26 @@ class Server:
:rtype: Optional[str]
"""
source_obj = state.client.sources[data["source"]]
entry = await source_obj.get_entry(
data["performer"], data["ident"], artist=data["artist"], title=data["title"]
)
if entry is None:
try:
entry = await source_obj.get_entry(
data["performer"], data["ident"], artist=data["artist"], title=data["title"]
)
if entry is None:
await self.sio.emit(
"msg",
{"msg": f"Unable to add to the waiting room: {data['ident']}. Maybe try again?"},
room=sid,
)
return None
except EntryNotValid as e:
await self.sio.emit(
"msg",
{"msg": f"Unable to add to the waiting room: {data['ident']}. Maybe try again?"},
{"msg": f"Unable to add to the waiting room: {data['ident']}. {e}"},
room=sid,
)
return None
if "uid" not in data or (
(data["uid"] is not None and len(list(state.queue.find_by_uid(data["uid"]))) == 0)
or (data["uid"] is None and state.queue.find_by_name(data["performer"]) is None)
@ -511,17 +521,24 @@ class Server:
source_obj = state.client.sources[data["source"]]
entry = await source_obj.get_entry(
data["performer"],
data["ident"],
artist=data.get("artist", None),
title=data.get("title", None),
)
if entry is None:
try:
entry = await source_obj.get_entry(
data["performer"],
data["ident"],
artist=data.get("artist", None),
title=data.get("title", None),
)
if entry is None:
await self.sio.emit(
"msg",
{"msg": f"Unable to append {data['ident']}. Maybe try again?"},
room=sid,
)
return None
except EntryNotValid as e:
await self.sio.emit(
"msg",
{"msg": f"Unable to append {data['ident']}. Maybe try again?"},
{"msg": f"Unable to append {data['ident']}. {e}"},
room=sid,
)
return None
@ -564,14 +581,22 @@ class Server:
source_obj = state.client.sources[data["source"]]
entry = await source_obj.get_entry(
data["performer"], data["ident"], artist=data["artist"], title=data["title"]
)
try:
entry = await source_obj.get_entry(
data["performer"], data["ident"], artist=data["artist"], title=data["title"]
)
if entry is None:
if entry is None:
await self.sio.emit(
"msg",
{"msg": f"Unable to append {data['ident']}. Maybe try again?"},
room=sid,
)
return None
except EntryNotValid as e:
await self.sio.emit(
"msg",
{"msg": f"Unable to append {data['ident']}. Maybe try again?"},
{"msg": f"Unable to append {data['ident']}. {e}"},
room=sid,
)
return None
@ -605,9 +630,17 @@ class Server:
lambda item: item.update(**data["meta"], incomplete_data=False),
)
for entry in state.waiting_room:
if entry.uuid == data["uuid"] or str(entry.uuid) == data["uuid"]:
entry.update(**data["meta"], incomplete_data=False)
entry = state.queue.find_by_uuid(data["uuid"])
if entry is not None:
source = entry.source
source_obj = state.client.sources[source]
if not source_obj.is_valid(entry):
await self.log_to_playback(state, f"Entry {entry.ident} is not valid.", level="error")
await state.queue.remove(entry)
else:
for entry in state.waiting_room:
if entry.uuid == data["uuid"] or str(entry.uuid) == data["uuid"]:
entry.update(**data["meta"], incomplete_data=False)
await self.broadcast_state(state)

View file

@ -4,6 +4,8 @@ import asyncio
import os
from typing import TYPE_CHECKING, Any, Optional
from syng.entry import Entry
try:
from pymediainfo import MediaInfo
@ -39,6 +41,9 @@ class FileBasedSource(Source):
self.extensions: list[str] = config["extensions"] if "extensions" in config else ["mp3+cdg"]
self.extra_mpv_options = {"scale": "oversample"}
def is_valid(self, entry: Entry) -> bool:
return entry.ident in self._index and entry.source == self.source_name
def has_correct_extension(self, path: Optional[str]) -> bool:
"""
Check if a `path` has a correct extension.

View file

@ -29,6 +29,9 @@ from ..config import BoolOption, ConfigOption
# logger: logging.Logger = logging.getLogger(__name__)
class EntryNotValid(Exception):
"""Raised when an entry is not valid for a source."""
@dataclass
class DLFilesEntry:
@ -127,6 +130,19 @@ class Source(ABC):
self.build_index = config.get("build_index", False)
self.apply_config(config)
def is_valid(self, entry: Entry) -> bool:
"""
Check if the entry is valid.
Each source can implement this method to check if the entry is valid.
:param entry: The entry to check
:type entry: Entry
:returns: True if the entry is valid, False otherwise.
:rtype: bool
"""
return True
async def get_entry(
self,
performer: str,
@ -153,9 +169,8 @@ class Source(ABC):
:returns: New entry for the identifier, or None, if the ident is
invalid.
:rtype: Optional[Entry]
:raises EntryNotValid: If the entry is not valid for the source.
"""
if ident not in self._index:
return None
res: Result = Result.from_filename(ident, self.source_name)
entry = Entry(
@ -168,8 +183,8 @@ class Source(ABC):
performer=performer,
incomplete_data=True,
)
if not await self.is_valid(entry):
return None
if not self.is_valid(entry):
raise EntryNotValid(f"Entry {entry} is not valid for source {self.source_name}")
return entry
async def search(self, query: str) -> list[Result]: