Work on provider manager and UI

This commit is contained in:
2020-10-18 19:36:26 +03:00
parent c8b2ef77e6
commit 45d50a1bff
11 changed files with 219 additions and 63 deletions

View File

@ -1,21 +1,20 @@
import json
import logging
from typing import List, Dict, Union, Iterable
from typing import List, Dict, Union, Iterable, Optional
from django.db import transaction
from YtManagerApp.models import VideoProviderConfig, Video, Subscription
from YtManagerApp.providers.video_provider import VideoProvider, InvalidURLError
import json
from collections import namedtuple
from YtManagerApp.providers.video_provider import VideoProvider, InvalidURLError, VideoProviderState
log = logging.getLogger("VideoProviderManager")
VideoProviderInfo = namedtuple('VideoProviderInfo', ['id', 'name', 'is_configured', 'description'])
class VideoProviderManager(object):
def __init__(self, registered_providers: List[VideoProvider]):
self._registered_providers: Dict[str, VideoProvider] = {}
self._configured_providers: Dict[str, VideoProvider] = {}
self._pending_configs: Dict[str, VideoProviderConfig] = {}
for rp in registered_providers:
self.register_provider(rp)
self._load()
@ -39,6 +38,28 @@ class VideoProviderManager(object):
self._configure(provider, self._pending_configs[provider.id])
del self._pending_configs[provider.id]
def configure_provider(self, provider_id: str, config: Optional[Dict[str, any]]):
provider = self.get(provider_id)
if config is not None:
provider.configure(config)
with transaction.atomic():
cfg, _ = VideoProviderConfig.objects.get_or_create(provider_id=provider_id)
cfg.settings = json.dumps(config)
cfg.save()
provider.state = VideoProviderState.OK
else:
provider.unconfigure()
VideoProviderConfig.objects.filter(provider_id=provider_id).delete()
provider.state = VideoProviderState.NOT_CONFIGURED
def get_provider_config(self, provider_id: str):
cfg = VideoProviderConfig.objects.filter(provider_id=provider_id).first()
if cfg is not None:
return json.loads(cfg.settings)
return None
def _load(self) -> None:
# Loads configuration from database
for config in VideoProviderConfig.objects.all():
@ -56,8 +77,8 @@ class VideoProviderManager(object):
def _configure(self, provider, config):
settings = json.loads(config.settings)
provider.configure(settings)
provider.state = VideoProviderState.OK
log.info(f"Configured video provider {provider.id}")
self._configured_providers[provider.id] = provider
def get(self, item: Union[str, Subscription, Video]):
"""
@ -79,12 +100,13 @@ class VideoProviderManager(object):
:param url:
:return:
"""
for provider in self._configured_providers.values():
try:
provider.validate_subscription_url(url)
return
except InvalidURLError:
pass
for provider in self._registered_providers.values():
if provider.state == VideoProviderState.OK:
try:
provider.validate_subscription_url(url)
return
except InvalidURLError:
pass
raise InvalidURLError("The given URL is not valid for any of the supported sites!")
@ -94,23 +116,16 @@ class VideoProviderManager(object):
:param url:
:return:
"""
for provider in self._configured_providers.values():
try:
provider.validate_subscription_url(url)
# Found the right provider
return provider.fetch_subscription(url)
except InvalidURLError:
pass
for provider in self._registered_providers.values():
if provider.state == VideoProviderState.OK:
try:
provider.validate_subscription_url(url)
# Found the right provider
return provider.fetch_subscription(url)
except InvalidURLError:
pass
raise InvalidURLError("The given URL is not valid for any of the supported sites!")
def get_available_providers(self) -> Iterable[VideoProviderInfo]:
"""
Gets a list of available providers and some basic information about them.
:return: List of dictionary entries
"""
for key, provider in self._registered_providers.items():
yield VideoProviderInfo(id=key,
name=provider.name,
description=provider.description,
is_configured=(key in self._configured_providers))
def get_available_providers(self) -> Iterable[VideoProvider]:
return self._registered_providers.values()