feat(playout): integrate api-client v2 calls

This commit is contained in:
jo 2022-07-22 15:41:38 +02:00 committed by Kyle Robbertze
parent d4110020c0
commit d9725003c5
6 changed files with 66 additions and 59 deletions

View File

@ -1,6 +1,6 @@
from pathlib import Path from pathlib import Path
from libretime_shared.config import BaseConfig, RabbitMQConfig from libretime_shared.config import BaseConfig, GeneralConfig, RabbitMQConfig
from pydantic import BaseModel from pydantic import BaseModel
from typing_extensions import Literal from typing_extensions import Literal
@ -23,5 +23,6 @@ class PlayoutConfig(BaseModel):
class Config(BaseConfig): class Config(BaseConfig):
general: GeneralConfig
rabbitmq: RabbitMQConfig = RabbitMQConfig() rabbitmq: RabbitMQConfig = RabbitMQConfig()
playout: PlayoutConfig = PlayoutConfig() playout: PlayoutConfig = PlayoutConfig()

View File

@ -129,7 +129,10 @@ def cli(log_level: str, log_filepath: Optional[Path], config_filepath: Optional[
signal.signal(signal.SIGINT, keyboardInterruptHandler) signal.signal(signal.SIGINT, keyboardInterruptHandler)
legacy_client = LegacyClient() legacy_client = LegacyClient()
api_client = ApiClient() api_client = ApiClient(
base_url=config.general.public_url,
api_key=config.general.api_key,
)
g = Global(legacy_client) g = Global(legacy_client)
while not g.selfcheck(): while not g.selfcheck():

View File

@ -8,7 +8,7 @@ from threading import Thread
from libretime_api_client.v2 import ApiClient from libretime_api_client.v2 import ApiClient
from loguru import logger from loguru import logger
from requests.exceptions import ConnectionError, Timeout from requests.exceptions import ConnectionError, HTTPError, Timeout
class PypoFile(Thread): class PypoFile(Thread):
@ -22,11 +22,9 @@ class PypoFile(Thread):
""" """
Copy media_item from local library directory to local cache directory. Copy media_item from local library directory to local cache directory.
""" """
src = media_item["uri"] file_id = media_item["id"]
dst = media_item["dst"] dst = media_item["dst"]
src_size = media_item["filesize"]
dst_exists = True dst_exists = True
try: try:
dst_size = os.path.getsize(dst) dst_size = os.path.getsize(dst)
@ -43,33 +41,26 @@ class PypoFile(Thread):
# become an issue here... This needs proper cache management. # become an issue here... This needs proper cache management.
# https://github.com/libretime/libretime/issues/756#issuecomment-477853018 # https://github.com/libretime/libretime/issues/756#issuecomment-477853018
# https://github.com/libretime/libretime/pull/845 # https://github.com/libretime/libretime/pull/845
logger.debug( logger.debug(f"found file {file_id} in cache {dst}, skipping copy...")
"file %s already exists in local cache as %s, skipping copying..."
% (src, dst)
)
else: else:
do_copy = True do_copy = True
media_item["file_ready"] = not do_copy media_item["file_ready"] = not do_copy
if do_copy: if do_copy:
logger.info(f"copying from {src} to local cache {dst}") logger.info(f"copying file {file_id} to cache {dst}")
try: try:
with open(dst, "wb") as handle: with open(dst, "wb") as handle:
logger.info(media_item) logger.info(media_item)
response = self.api_client.services.file_download_url( try:
id=media_item["id"] response = self.api_client.download_file(file_id)
) for chunk in response.iter_content(chunk_size=1024):
handle.write(chunk)
if not response.ok: except HTTPError as exception:
logger.error(response)
raise Exception( raise Exception(
"%s - Error occurred downloading file" f"could not download file {media_item['id']}"
% response.status_code ) from exception
)
for chunk in response.iter_content(chunk_size=1024):
handle.write(chunk)
# make file world readable and owner writable # make file world readable and owner writable
os.chmod(dst, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) os.chmod(dst, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
@ -82,7 +73,7 @@ class PypoFile(Thread):
media_item["file_ready"] = True media_item["file_ready"] = True
except Exception as e: except Exception as e:
logger.error(f"Could not copy from {src} to {dst}") logger.error(f"could not copy file {file_id} to {dst}")
logger.error(e) logger.error(e)
def report_file_size_and_md5_to_api(self, file_path, file_id): def report_file_size_and_md5_to_api(self, file_path, file_id):
@ -109,8 +100,10 @@ class PypoFile(Thread):
"Could not update media file %s with file size and md5 hash:" % file_id "Could not update media file %s with file size and md5 hash:" % file_id
) )
try: try:
payload = {"filesize": file_size, "md5": md5_hash} self.api_client.update_file(
response = self.api_client.update_file(file_id, payload) file_id,
json={"filesize": file_size, "md5": md5_hash},
)
except (ConnectionError, Timeout): except (ConnectionError, Timeout):
logger.error(error_msg) logger.error(error_msg)
except Exception as e: except Exception as e:

View File

@ -25,29 +25,29 @@ def get_schedule(api_client: ApiClient):
current_time_str = current_time.isoformat(timespec="seconds") current_time_str = current_time.isoformat(timespec="seconds")
end_time_str = end_time.isoformat(timespec="seconds") end_time_str = end_time.isoformat(timespec="seconds")
schedule = api_client.services.schedule_url( schedule = api_client.list_schedule(
params={ params={
"ends_after": f"{current_time_str}Z", "ends_after": f"{current_time_str}Z",
"ends_before": f"{end_time_str}Z", "ends_before": f"{end_time_str}Z",
"overbooked": False, "overbooked": False,
"position_status__gt": 0, "position_status__gt": 0,
} }
) ).json()
events = {} events = {}
for item in schedule: for item in schedule:
item["starts_at"] = isoparse(item["starts_at"]) item["starts_at"] = isoparse(item["starts_at"])
item["ends_at"] = isoparse(item["ends_at"]) item["ends_at"] = isoparse(item["ends_at"])
show_instance = api_client.services.show_instance_url(id=item["instance_id"]) show_instance = api_client.get_show_instance(item["instance_id"]).json()
show = api_client.services.show_url(id=show_instance["show_id"]) show = api_client.get_show(show_instance["show_id"]).json()
if item["file"]: if item["file"]:
file = api_client.services.file_url(id=item["file_id"]) file = api_client.get_file(item["file_id"]).json()
events.update(generate_file_events(item, file, show)) events.update(generate_file_events(item, file, show))
elif item["stream"]: elif item["stream"]:
webstream = api_client.services.webstream_url(id=item["stream_id"]) webstream = api_client.get_webstream(item["stream_id"]).json()
events.update(generate_webstream_events(item, webstream, show)) events.update(generate_webstream_events(item, webstream, show))
return {"media": events} return {"media": events}

View File

@ -40,6 +40,7 @@ setup(
extras_require={ extras_require={
"dev": [ "dev": [
"distro", "distro",
"requests-mock",
f"libretime-api-client @ file://localhost{here.parent / 'api-client'}", f"libretime-api-client @ file://localhost{here.parent / 'api-client'}",
f"libretime-shared @ file://localhost{here.parent / 'shared'}", f"libretime-shared @ file://localhost{here.parent / 'shared'}",
], ],

View File

@ -1,10 +1,17 @@
import pytest
from libretime_api_client.v2 import ApiClient
from libretime_playout.player.schedule import get_schedule from libretime_playout.player.schedule import get_schedule
class ApiClientServicesMock: @pytest.fixture(name="api_client_mock")
@staticmethod def _api_client_mock(requests_mock):
def schedule_url(*args, **kwargs): base_url = "http://localhost"
return [ api_client = ApiClient(base_url=base_url, api_key="test_key")
requests_mock.get(
f"{base_url}/api/v2/schedule",
json=[
{ {
"id": 17, "id": 17,
"starts_at": "2022-03-04T15:30:00Z", "starts_at": "2022-03-04T15:30:00Z",
@ -31,23 +38,26 @@ class ApiClientServicesMock:
"cue_out": "00:30:00", "cue_out": "00:30:00",
"instance_id": 3, "instance_id": 3,
}, },
] ],
)
@staticmethod requests_mock.get(
def show_instance_url(*args, **kwargs): f"{base_url}/api/v2/show-instances/3",
return { json={
"show_id": 3, "show_id": 3,
} },
)
@staticmethod requests_mock.get(
def show_url(*args, **kwargs): f"{base_url}/api/v2/shows/3",
return { json={
"name": "Test", "name": "Test",
} },
)
@staticmethod requests_mock.get(
def file_url(*args, **kwargs): f"{base_url}/api/v2/files/1",
return { json={
"id": 1, "id": 1,
"url": None, "url": None,
"replay_gain": "-8.77", "replay_gain": "-8.77",
@ -55,24 +65,23 @@ class ApiClientServicesMock:
"artist_name": "Bag Raiders", "artist_name": "Bag Raiders",
"track_title": "Shooting Stars", "track_title": "Shooting Stars",
"mime": "audio/mp3", "mime": "audio/mp3",
} },
)
@staticmethod requests_mock.get(
def webstream_url(*args, **kwargs): f"{base_url}/api/v2/webstreams/1",
return { json={
"id": 1, "id": 1,
"name": "Test", "name": "Test",
"url": "http://some-other-radio:8800/main.ogg", "url": "http://some-other-radio:8800/main.ogg",
} },
)
return api_client
class ApiClientMock: def test_get_schedule(api_client_mock: ApiClient):
services = ApiClientServicesMock() assert get_schedule(api_client_mock) == {
def test_get_schedule():
api_client = ApiClientMock()
assert get_schedule(api_client) == {
"media": { "media": {
"2022-03-04-15-30-00": { "2022-03-04-15-30-00": {
"type": "file", "type": "file",