Searching and adding to the queue now emits an ID to the client

This commit is contained in:
Christoph Stahl 2025-01-31 16:42:10 +01:00
parent 55a3685c76
commit 02ec988f90
2 changed files with 65 additions and 25 deletions

View file

@ -334,6 +334,7 @@ class Client:
""" """
query = data["query"] query = data["query"]
sid = data["sid"] sid = data["sid"]
search_id = data["search_id"]
results_list = await asyncio.gather( results_list = await asyncio.gather(
*[source.search(query) for source in self.sources.values()] *[source.search(query) for source in self.sources.values()]
) )
@ -344,7 +345,9 @@ class Client:
for search_result in source_result for search_result in source_result
] ]
await self.sio.emit("search-results", {"results": results, "sid": sid}) await self.sio.emit(
"search-results", {"results": results, "sid": sid, "search_id": search_id}
)
async def handle_client_registered(self, data: dict[str, Any]) -> None: async def handle_client_registered(self, data: dict[str, Any]) -> None:
""" """

View file

@ -19,6 +19,7 @@ import hashlib
import os import os
import random import random
import string import string
import uuid
from json.decoder import JSONDecodeError from json.decoder import JSONDecodeError
from argparse import Namespace from argparse import Namespace
from dataclasses import dataclass from dataclasses import dataclass
@ -281,7 +282,7 @@ class Server:
@with_state @with_state
async def handle_waiting_room_append( async def handle_waiting_room_append(
self, state: State, sid: str, data: dict[str, Any] self, state: State, sid: str, data: dict[str, Any]
) -> None: ) -> Optional[str]:
""" """
Append a song to the waiting room. Append a song to the waiting room.
@ -294,7 +295,8 @@ class Server:
:param data: A dictionary encoding the entry, that should be added to the :param data: A dictionary encoding the entry, that should be added to the
waiting room. waiting room.
:type data: dict[str, Any] :type data: dict[str, Any]
:rtype: None :return: The uuid of the added entry or None if the entry could not be added
:rtype: Optional[str]
""" """
source_obj = state.client.sources[data["source"]] source_obj = state.client.sources[data["source"]]
entry = await source_obj.get_entry( entry = await source_obj.get_entry(
@ -325,6 +327,7 @@ class Server:
entry, entry,
room=state.sid, room=state.sid,
) )
return str(entry.uuid)
async def append_to_queue( async def append_to_queue(
self, state: State, entry: Entry, report_to: Optional[str] = None self, state: State, entry: Entry, report_to: Optional[str] = None
@ -421,7 +424,7 @@ class Server:
await self.sio.emit("err", {"type": "JSON_MALFORMED"}, room=sid) await self.sio.emit("err", {"type": "JSON_MALFORMED"}, room=sid)
@with_state @with_state
async def handle_append(self, state: State, sid: str, data: dict[str, Any]) -> None: async def handle_append(self, state: State, sid: str, data: dict[str, Any]) -> Optional[str]:
""" """
Handle the "append" message. Handle the "append" message.
@ -454,7 +457,8 @@ class Server:
:param data: A dictionary encoding the entry, that should be added to the :param data: A dictionary encoding the entry, that should be added to the
queue. queue.
:type data: dict[str, Any] :type data: dict[str, Any]
:rtype: None :return: The uuid of the added entry or None if the entry could not be added
:rtype: Optional[str]
""" """
if len(data["performer"]) > 50: if len(data["performer"]) > 50:
await self.sio.emit("err", {"type": "NAME_LENGTH", "name": data["performer"]}, room=sid) await self.sio.emit("err", {"type": "NAME_LENGTH", "name": data["performer"]}, room=sid)
@ -510,9 +514,12 @@ class Server:
entry.uid = data["uid"] if "uid" in data else None entry.uid = data["uid"] if "uid" in data else None
await self.append_to_queue(state, entry, sid) await self.append_to_queue(state, entry, sid)
return str(entry.uuid)
@with_state @with_state
async def handle_append_anyway(self, state: State, sid: str, data: dict[str, Any]) -> None: async def handle_append_anyway(
self, state: State, sid: str, data: dict[str, Any]
) -> Optional[str]:
""" """
Appends a song to the queue, even if the performer is already in queue. Appends a song to the queue, even if the performer is already in queue.
@ -520,6 +527,9 @@ class Server:
in queue. in queue.
Only if the waiting_room_policy is not configured as forced. Only if the waiting_room_policy is not configured as forced.
:return: The uuid of the added entry or None if the entry could not be added
:rtype: Optional[str]
""" """
if len(data["performer"]) > 50: if len(data["performer"]) > 50:
await self.sio.emit("err", {"type": "NAME_LENGTH", "name": data["performer"]}, room=sid) await self.sio.emit("err", {"type": "NAME_LENGTH", "name": data["performer"]}, room=sid)
@ -554,6 +564,7 @@ class Server:
entry.uid = data["uid"] if "uid" in data else None entry.uid = data["uid"] if "uid" in data else None
await self.append_to_queue(state, entry, sid) await self.append_to_queue(state, entry, sid)
return str(entry.uuid)
@playback @playback
@with_state @with_state
@ -922,7 +933,7 @@ class Server:
:type sid: str :type sid: str
:param data: A dictionary, containing at least a "room" entry. :param data: A dictionary, containing at least a "room" entry.
:type data: dict[str, Any] :type data: dict[str, Any]
:returns: True, if the room exist, False otherwise :return: True, if the room exist, False otherwise
:rtype: bool :rtype: bool
""" """
if data["room"] in self.clients: if data["room"] in self.clients:
@ -946,7 +957,7 @@ class Server:
:type sid: str: :type sid: str:
:param data: A dictionary with at least a "secret" entry. :param data: A dictionary with at least a "secret" entry.
:type data: dict[str, Any] :type data: dict[str, Any]
:returns: True, if the secret is correct, False otherwise :return: True, if the secret is correct, False otherwise
:rtype: bool :rtype: bool
""" """
is_admin: bool = data["secret"] == state.client.config["secret"] is_admin: bool = data["secret"] == state.client.config["secret"]
@ -1063,7 +1074,7 @@ class Server:
await self.sio.leave_room(sid, room) await self.sio.leave_room(sid, room)
@with_state @with_state
async def handle_search(self, state: State, sid: str, data: dict[str, Any]) -> None: async def handle_search(self, state: State, sid: str, data: dict[str, Any]) -> str:
""" """
Handle the "search" message. Handle the "search" message.
@ -1078,27 +1089,48 @@ class Server:
:type sid: str :type sid: str
:param data: A dictionary with at least a "query" entry. :param data: A dictionary with at least a "query" entry.
:type data: dict[str, str] :type data: dict[str, str]
:rtype: None :return: The search id
:rtype: str
""" """
query = data["query"] query = data["query"]
search_id = uuid.uuid4()
if ( if (
self.app["type"] != "restricted" self.app["type"] != "restricted"
or "key" in state.client.config or "key" in state.client.config
and self.check_registration(state.client.config["key"]) and self.check_registration(state.client.config["key"])
): ):
asyncio.create_task(self.search_and_emit(search_id, query, state, sid))
else:
await self.sio.emit(
"search", {"query": query, "sid": sid, "search_id": search_id}, room=state.sid
)
return str(search_id)
async def search_and_emit(
self, search_id: uuid.UUID, query: str, state: State, sid: str
) -> None:
"""
Search for a query on a source and emit the results.
:param search_id: The search id
:type search_id: uuid.UUID
:param query: The query to search for
:type query: str
:param state: The state of the room
:type state: State
:param sid: The session id of the client
:type sid: str
:rtype: list[Result]
"""
results_list = await asyncio.gather( results_list = await asyncio.gather(
*[ *[state.client.sources[source].search(query) for source in state.client.sources_prio]
state.client.sources[source].search(query)
for source in state.client.sources_prio
]
) )
results = [ results = [
search_result for source_result in results_list for search_result in source_result search_result for source_result in results_list for search_result in source_result
] ]
await self.send_search_results(sid, results) await self.send_search_results(sid, results, search_id)
else:
await self.sio.emit("search", {"query": query, "sid": sid}, room=state.sid)
@playback @playback
async def handle_search_results(self, sid: str, data: dict[str, Any]) -> None: async def handle_search_results(self, sid: str, data: dict[str, Any]) -> None:
@ -1111,6 +1143,7 @@ class Server:
The data dictionary should have the following keys: The data dictionary should have the following keys:
- `sid`, the session id of the web client (str) - `sid`, the session id of the web client (str)
- `results`, a list of search results (list[dict[str, Any]]) - `results`, a list of search results (list[dict[str, Any]])
- `search_id`, the search id (str) (Optional)
:param sid: The session id of the playback client :param sid: The session id of the playback client
:type sid: str :type sid: str
@ -1119,11 +1152,15 @@ class Server:
:rtype: None :rtype: None
""" """
web_sid = data["sid"] web_sid = data["sid"]
search_id = data["search_id"] if "search_id" in data else None
results = [Result.from_dict(result) for result in data["results"]] results = [Result.from_dict(result) for result in data["results"]]
await self.send_search_results(web_sid, results) await self.send_search_results(web_sid, results, search_id)
async def send_search_results(self, sid: str, results: list[Result]) -> None: async def send_search_results(
self, sid: str, results: list[Result], search_id: Optional[uuid.UUID]
) -> None:
""" """
Send search results to a client. Send search results to a client.
@ -1135,7 +1172,7 @@ class Server:
""" """
await self.sio.emit( await self.sio.emit(
"search-results", "search-results",
{"results": results}, {"results": results, "search_id": search_id},
room=sid, room=sid,
) )