feat(api): split api into multiple apps (#1626)
Fixes #1622 - split the api into 4 apps: core, history, schedule, storage - exploded the settings into testing/prod
This commit is contained in:
parent
87d2da9d84
commit
fce988aef1
|
@ -202,7 +202,6 @@ jobs:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
LIBRETIME_GENERAL_API_KEY: test_key
|
|
||||||
LIBRETIME_DATABASE_HOST: postgres
|
LIBRETIME_DATABASE_HOST: postgres
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
|
@ -13,4 +13,4 @@ clean: .clean
|
||||||
|
|
||||||
test: $(VENV)
|
test: $(VENV)
|
||||||
source $(VENV)/bin/activate
|
source $(VENV)/bin/activate
|
||||||
LIBRETIME_DEBUG=True $(VENV)/bin/libretime-api test libretime_api
|
DJANGO_SETTINGS_MODULE=libretime_api.settings.testing libretime-api test libretime_api
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
FILTER_NUMERICAL_LOOKUPS = [
|
||||||
|
"exact",
|
||||||
|
"gt",
|
||||||
|
"lt",
|
||||||
|
"gte",
|
||||||
|
"lte",
|
||||||
|
"range",
|
||||||
|
]
|
|
@ -0,0 +1,5 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
fixture_path = Path(__file__).resolve().parent
|
||||||
|
|
||||||
|
AUDIO_FILENAME = "song.mp3"
|
|
@ -1,8 +0,0 @@
|
||||||
from django.apps import AppConfig
|
|
||||||
from django.db.models.signals import pre_save
|
|
||||||
|
|
||||||
|
|
||||||
class LibreTimeAPIConfig(AppConfig):
|
|
||||||
name = "libretime_api"
|
|
||||||
verbose_name = "LibreTime API"
|
|
||||||
default_auto_field = "django.db.models.AutoField"
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
"""
|
||||||
|
ASGI config for libretime_api project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "libretime_api.settings.prod")
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class CoreConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "libretime_api.core"
|
||||||
|
verbose_name = "LibreTime Core API"
|
|
@ -0,0 +1,7 @@
|
||||||
|
from .auth import LoginAttempt, Session, UserToken
|
||||||
|
from .country import Country
|
||||||
|
from .preference import Preference, StreamSetting
|
||||||
|
from .role import ADMIN, DJ, GUEST, PROGRAM_MANAGER, USER_TYPES
|
||||||
|
from .service import ServiceRegister
|
||||||
|
from .user import User, UserManager
|
||||||
|
from .worker import CeleryTask, ThirdPartyTrackReference
|
|
@ -0,0 +1,37 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class UserToken(models.Model):
|
||||||
|
user = models.ForeignKey("User", models.DO_NOTHING)
|
||||||
|
action = models.CharField(max_length=255)
|
||||||
|
token = models.CharField(unique=True, max_length=40)
|
||||||
|
created = models.DateTimeField()
|
||||||
|
|
||||||
|
def get_owner(self):
|
||||||
|
return self.user
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "cc_subjs_token"
|
||||||
|
|
||||||
|
|
||||||
|
class Session(models.Model):
|
||||||
|
sessid = models.CharField(primary_key=True, max_length=32)
|
||||||
|
userid = models.ForeignKey(
|
||||||
|
"User", models.DO_NOTHING, db_column="userid", blank=True, null=True
|
||||||
|
)
|
||||||
|
login = models.CharField(max_length=255, blank=True, null=True)
|
||||||
|
ts = models.DateTimeField(blank=True, null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "cc_sess"
|
||||||
|
|
||||||
|
|
||||||
|
class LoginAttempt(models.Model):
|
||||||
|
ip = models.CharField(primary_key=True, max_length=32)
|
||||||
|
attempts = models.IntegerField(blank=True, null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "cc_login_attempts"
|
|
@ -14,14 +14,6 @@ class Preference(models.Model):
|
||||||
unique_together = (("subjid", "keystr"),)
|
unique_together = (("subjid", "keystr"),)
|
||||||
|
|
||||||
|
|
||||||
class MountName(models.Model):
|
|
||||||
mount_name = models.CharField(max_length=1024)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "cc_mount_name"
|
|
||||||
|
|
||||||
|
|
||||||
class StreamSetting(models.Model):
|
class StreamSetting(models.Model):
|
||||||
keyname = models.CharField(primary_key=True, max_length=64)
|
keyname = models.CharField(primary_key=True, max_length=64)
|
||||||
value = models.CharField(max_length=255, blank=True, null=True)
|
value = models.CharField(max_length=255, blank=True, null=True)
|
|
@ -1,43 +1,37 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from django.contrib import auth
|
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, Permission
|
||||||
from django.contrib.auth.models import AbstractBaseUser, Permission
|
|
||||||
from django.core.exceptions import PermissionDenied
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from libretime_api.managers import UserManager
|
from ...permission_constants import GROUPS
|
||||||
from libretime_api.permission_constants import GROUPS
|
from .role import ADMIN, USER_TYPES
|
||||||
|
|
||||||
from .user_constants import ADMIN, USER_TYPES
|
|
||||||
|
|
||||||
|
|
||||||
class LoginAttempt(models.Model):
|
|
||||||
ip = models.CharField(primary_key=True, max_length=32)
|
|
||||||
attempts = models.IntegerField(blank=True, null=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "cc_login_attempts"
|
|
||||||
|
|
||||||
|
|
||||||
class Session(models.Model):
|
|
||||||
sessid = models.CharField(primary_key=True, max_length=32)
|
|
||||||
userid = models.ForeignKey(
|
|
||||||
"User", models.DO_NOTHING, db_column="userid", blank=True, null=True
|
|
||||||
)
|
|
||||||
login = models.CharField(max_length=255, blank=True, null=True)
|
|
||||||
ts = models.DateTimeField(blank=True, null=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "cc_sess"
|
|
||||||
|
|
||||||
|
|
||||||
USER_TYPE_CHOICES = ()
|
USER_TYPE_CHOICES = ()
|
||||||
for item in USER_TYPES.items():
|
for item in USER_TYPES.items():
|
||||||
USER_TYPE_CHOICES = USER_TYPE_CHOICES + (item,)
|
USER_TYPE_CHOICES = USER_TYPE_CHOICES + (item,)
|
||||||
|
|
||||||
|
|
||||||
|
class UserManager(BaseUserManager):
|
||||||
|
def create_user(self, username, type, email, first_name, last_name, password):
|
||||||
|
user = self.model(
|
||||||
|
username=username,
|
||||||
|
type=type,
|
||||||
|
email=email,
|
||||||
|
first_name=first_name,
|
||||||
|
last_name=last_name,
|
||||||
|
)
|
||||||
|
user.set_password(password)
|
||||||
|
user.save(using=self._db)
|
||||||
|
return user
|
||||||
|
|
||||||
|
def create_superuser(self, username, email, first_name, last_name, password):
|
||||||
|
user = self.create_user(username, "A", email, first_name, last_name, password)
|
||||||
|
return user
|
||||||
|
|
||||||
|
def get_by_natural_key(self, username):
|
||||||
|
return self.get(username=username)
|
||||||
|
|
||||||
|
|
||||||
class User(AbstractBaseUser):
|
class User(AbstractBaseUser):
|
||||||
username = models.CharField(db_column="login", unique=True, max_length=255)
|
username = models.CharField(db_column="login", unique=True, max_length=255)
|
||||||
password = models.CharField(
|
password = models.CharField(
|
||||||
|
@ -132,17 +126,3 @@ class User(AbstractBaseUser):
|
||||||
class Meta:
|
class Meta:
|
||||||
managed = False
|
managed = False
|
||||||
db_table = "cc_subjs"
|
db_table = "cc_subjs"
|
||||||
|
|
||||||
|
|
||||||
class UserToken(models.Model):
|
|
||||||
user = models.ForeignKey(User, models.DO_NOTHING)
|
|
||||||
action = models.CharField(max_length=255)
|
|
||||||
token = models.CharField(unique=True, max_length=40)
|
|
||||||
created = models.DateTimeField()
|
|
||||||
|
|
||||||
def get_owner(self):
|
|
||||||
return self.user
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "cc_subjs_token"
|
|
|
@ -1,6 +1,18 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class ThirdPartyTrackReference(models.Model):
|
||||||
|
service = models.CharField(max_length=256)
|
||||||
|
foreign_id = models.CharField(unique=True, max_length=256, blank=True, null=True)
|
||||||
|
file = models.ForeignKey("storage.File", models.DO_NOTHING, blank=True, null=True)
|
||||||
|
upload_time = models.DateTimeField(blank=True, null=True)
|
||||||
|
status = models.CharField(max_length=256, blank=True, null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "third_party_track_references"
|
||||||
|
|
||||||
|
|
||||||
class CeleryTask(models.Model):
|
class CeleryTask(models.Model):
|
||||||
task_id = models.CharField(max_length=256)
|
task_id = models.CharField(max_length=256)
|
||||||
track_reference = models.ForeignKey(
|
track_reference = models.ForeignKey(
|
|
@ -0,0 +1,26 @@
|
||||||
|
from rest_framework import routers
|
||||||
|
|
||||||
|
from .views import (
|
||||||
|
CeleryTaskViewSet,
|
||||||
|
CountryViewSet,
|
||||||
|
LoginAttemptViewSet,
|
||||||
|
PreferenceViewSet,
|
||||||
|
ServiceRegisterViewSet,
|
||||||
|
SessionViewSet,
|
||||||
|
StreamSettingViewSet,
|
||||||
|
ThirdPartyTrackReferenceViewSet,
|
||||||
|
UserTokenViewSet,
|
||||||
|
UserViewSet,
|
||||||
|
)
|
||||||
|
|
||||||
|
router = routers.DefaultRouter()
|
||||||
|
router.register("countries", CountryViewSet)
|
||||||
|
router.register("login-attempts", LoginAttemptViewSet)
|
||||||
|
router.register("preferences", PreferenceViewSet)
|
||||||
|
router.register("service-registers", ServiceRegisterViewSet)
|
||||||
|
router.register("sessions", SessionViewSet)
|
||||||
|
router.register("stream-settings", StreamSettingViewSet)
|
||||||
|
router.register("users", UserViewSet)
|
||||||
|
router.register("user-tokens", UserTokenViewSet)
|
||||||
|
router.register("celery-tasks", CeleryTaskViewSet)
|
||||||
|
router.register("third-party-track-references", ThirdPartyTrackReferenceViewSet)
|
|
@ -0,0 +1,6 @@
|
||||||
|
from .auth import LoginAttemptSerializer, SessionSerializer, UserTokenSerializer
|
||||||
|
from .country import CountrySerializer
|
||||||
|
from .preference import PreferenceSerializer, StreamSettingSerializer
|
||||||
|
from .service import ServiceRegisterSerializer
|
||||||
|
from .user import UserSerializer
|
||||||
|
from .worker import CeleryTaskSerializer, ThirdPartyTrackReferenceSerializer
|
|
@ -0,0 +1,21 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import LoginAttempt, Session, UserToken
|
||||||
|
|
||||||
|
|
||||||
|
class UserTokenSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = UserToken
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class SessionSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Session
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class LoginAttemptSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = LoginAttempt
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,9 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import Country
|
||||||
|
|
||||||
|
|
||||||
|
class CountrySerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Country
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,15 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import Preference, StreamSetting
|
||||||
|
|
||||||
|
|
||||||
|
class PreferenceSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Preference
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class StreamSettingSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = StreamSetting
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,9 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import ServiceRegister
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceRegisterSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ServiceRegister
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,20 @@
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
|
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = get_user_model()
|
||||||
|
fields = [
|
||||||
|
"item_url",
|
||||||
|
"username",
|
||||||
|
"type",
|
||||||
|
"first_name",
|
||||||
|
"last_name",
|
||||||
|
"lastfail",
|
||||||
|
"skype_contact",
|
||||||
|
"jabber_contact",
|
||||||
|
"email",
|
||||||
|
"cell_phone",
|
||||||
|
"login_attempts",
|
||||||
|
]
|
|
@ -0,0 +1,15 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import CeleryTask, ThirdPartyTrackReference
|
||||||
|
|
||||||
|
|
||||||
|
class ThirdPartyTrackReferenceSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ThirdPartyTrackReference
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class CeleryTaskSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = CeleryTask
|
||||||
|
fields = "__all__"
|
|
@ -1,10 +1,8 @@
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.contrib.auth.models import Group
|
|
||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
from libretime_api.models import User
|
from ....permission_constants import GROUPS
|
||||||
from libretime_api.models.user_constants import DJ, GUEST
|
from ...models import DJ, GUEST, User
|
||||||
from libretime_api.permission_constants import GROUPS
|
|
||||||
|
|
||||||
|
|
||||||
class TestUserManager(APITestCase):
|
class TestUserManager(APITestCase):
|
|
@ -0,0 +1,7 @@
|
||||||
|
from .auth import LoginAttemptViewSet, SessionViewSet, UserTokenViewSet
|
||||||
|
from .country import CountryViewSet
|
||||||
|
from .preference import PreferenceViewSet, StreamSettingViewSet
|
||||||
|
from .service import ServiceRegisterViewSet
|
||||||
|
from .user import UserViewSet
|
||||||
|
from .version import version
|
||||||
|
from .worker import CeleryTaskViewSet, ThirdPartyTrackReferenceViewSet
|
|
@ -0,0 +1,22 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import LoginAttempt, Session, UserToken
|
||||||
|
from ..serializers import LoginAttemptSerializer, SessionSerializer, UserTokenSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class UserTokenViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = UserToken.objects.all()
|
||||||
|
serializer_class = UserTokenSerializer
|
||||||
|
model_permission_name = "usertoken"
|
||||||
|
|
||||||
|
|
||||||
|
class SessionViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Session.objects.all()
|
||||||
|
serializer_class = SessionSerializer
|
||||||
|
model_permission_name = "session"
|
||||||
|
|
||||||
|
|
||||||
|
class LoginAttemptViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = LoginAttempt.objects.all()
|
||||||
|
serializer_class = LoginAttemptSerializer
|
||||||
|
model_permission_name = "loginattempt"
|
|
@ -0,0 +1,10 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import Country
|
||||||
|
from ..serializers import CountrySerializer
|
||||||
|
|
||||||
|
|
||||||
|
class CountryViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Country.objects.all()
|
||||||
|
serializer_class = CountrySerializer
|
||||||
|
model_permission_name = "country"
|
|
@ -0,0 +1,16 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import Preference, StreamSetting
|
||||||
|
from ..serializers import PreferenceSerializer, StreamSettingSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class PreferenceViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Preference.objects.all()
|
||||||
|
serializer_class = PreferenceSerializer
|
||||||
|
model_permission_name = "preference"
|
||||||
|
|
||||||
|
|
||||||
|
class StreamSettingViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = StreamSetting.objects.all()
|
||||||
|
serializer_class = StreamSettingSerializer
|
||||||
|
model_permission_name = "streamsetting"
|
|
@ -0,0 +1,10 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import ServiceRegister
|
||||||
|
from ..serializers import ServiceRegisterSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceRegisterViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = ServiceRegister.objects.all()
|
||||||
|
serializer_class = ServiceRegisterSerializer
|
||||||
|
model_permission_name = "serviceregister"
|
|
@ -0,0 +1,12 @@
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ...permissions import IsAdminOrOwnUser
|
||||||
|
from ..serializers import UserSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class UserViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = get_user_model().objects.all()
|
||||||
|
serializer_class = UserSerializer
|
||||||
|
permission_classes = [IsAdminOrOwnUser]
|
||||||
|
model_permission_name = "user"
|
|
@ -0,0 +1,10 @@
|
||||||
|
from django.conf import settings
|
||||||
|
from rest_framework.decorators import api_view, permission_classes
|
||||||
|
from rest_framework.permissions import AllowAny
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(["GET"])
|
||||||
|
@permission_classes((AllowAny,))
|
||||||
|
def version(request, *args, **kwargs):
|
||||||
|
return Response({"api_version": settings.API_VERSION})
|
|
@ -0,0 +1,16 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import CeleryTask, ThirdPartyTrackReference
|
||||||
|
from ..serializers import CeleryTaskSerializer, ThirdPartyTrackReferenceSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class ThirdPartyTrackReferenceViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = ThirdPartyTrackReference.objects.all()
|
||||||
|
serializer_class = ThirdPartyTrackReferenceSerializer
|
||||||
|
model_permission_name = "thirdpartytrackreference"
|
||||||
|
|
||||||
|
|
||||||
|
class CeleryTaskViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = CeleryTask.objects.all()
|
||||||
|
serializer_class = CeleryTaskSerializer
|
||||||
|
model_permission_name = "celerytask"
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class HistoryConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "libretime_api.history"
|
||||||
|
verbose_name = "LibreTime History API"
|
|
@ -0,0 +1,8 @@
|
||||||
|
from .listener import ListenerCount, MountName, Timestamp
|
||||||
|
from .live import LiveLog
|
||||||
|
from .played import (
|
||||||
|
PlayoutHistory,
|
||||||
|
PlayoutHistoryMetadata,
|
||||||
|
PlayoutHistoryTemplate,
|
||||||
|
PlayoutHistoryTemplateField,
|
||||||
|
)
|
|
@ -0,0 +1,27 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class MountName(models.Model):
|
||||||
|
mount_name = models.CharField(max_length=1024)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "cc_mount_name"
|
||||||
|
|
||||||
|
|
||||||
|
class Timestamp(models.Model):
|
||||||
|
timestamp = models.DateTimeField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "cc_timestamp"
|
||||||
|
|
||||||
|
|
||||||
|
class ListenerCount(models.Model):
|
||||||
|
timestamp = models.ForeignKey("Timestamp", models.DO_NOTHING)
|
||||||
|
mount_name = models.ForeignKey("MountName", models.DO_NOTHING)
|
||||||
|
listener_count = models.IntegerField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "cc_listener_count"
|
|
@ -0,0 +1,11 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class LiveLog(models.Model):
|
||||||
|
state = models.CharField(max_length=32)
|
||||||
|
start_time = models.DateTimeField()
|
||||||
|
end_time = models.DateTimeField(blank=True, null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "cc_live_log"
|
|
@ -1,34 +1,12 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from .files import File
|
|
||||||
|
|
||||||
|
|
||||||
class ListenerCount(models.Model):
|
|
||||||
timestamp = models.ForeignKey("Timestamp", models.DO_NOTHING)
|
|
||||||
mount_name = models.ForeignKey("MountName", models.DO_NOTHING)
|
|
||||||
listener_count = models.IntegerField()
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "cc_listener_count"
|
|
||||||
|
|
||||||
|
|
||||||
class LiveLog(models.Model):
|
|
||||||
state = models.CharField(max_length=32)
|
|
||||||
start_time = models.DateTimeField()
|
|
||||||
end_time = models.DateTimeField(blank=True, null=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "cc_live_log"
|
|
||||||
|
|
||||||
|
|
||||||
class PlayoutHistory(models.Model):
|
class PlayoutHistory(models.Model):
|
||||||
file = models.ForeignKey(File, models.DO_NOTHING, blank=True, null=True)
|
file = models.ForeignKey("storage.File", models.DO_NOTHING, blank=True, null=True)
|
||||||
starts = models.DateTimeField()
|
starts = models.DateTimeField()
|
||||||
ends = models.DateTimeField(blank=True, null=True)
|
ends = models.DateTimeField(blank=True, null=True)
|
||||||
instance = models.ForeignKey(
|
instance = models.ForeignKey(
|
||||||
"ShowInstance", models.DO_NOTHING, blank=True, null=True
|
"schedule.ShowInstance", models.DO_NOTHING, blank=True, null=True
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -37,7 +15,7 @@ class PlayoutHistory(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class PlayoutHistoryMetadata(models.Model):
|
class PlayoutHistoryMetadata(models.Model):
|
||||||
history = models.ForeignKey(PlayoutHistory, models.DO_NOTHING)
|
history = models.ForeignKey("PlayoutHistory", models.DO_NOTHING)
|
||||||
key = models.CharField(max_length=128)
|
key = models.CharField(max_length=128)
|
||||||
value = models.CharField(max_length=128)
|
value = models.CharField(max_length=128)
|
||||||
|
|
||||||
|
@ -56,7 +34,7 @@ class PlayoutHistoryTemplate(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class PlayoutHistoryTemplateField(models.Model):
|
class PlayoutHistoryTemplateField(models.Model):
|
||||||
template = models.ForeignKey(PlayoutHistoryTemplate, models.DO_NOTHING)
|
template = models.ForeignKey("PlayoutHistoryTemplate", models.DO_NOTHING)
|
||||||
name = models.CharField(max_length=128)
|
name = models.CharField(max_length=128)
|
||||||
label = models.CharField(max_length=128)
|
label = models.CharField(max_length=128)
|
||||||
type = models.CharField(max_length=128)
|
type = models.CharField(max_length=128)
|
||||||
|
@ -66,11 +44,3 @@ class PlayoutHistoryTemplateField(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
managed = False
|
managed = False
|
||||||
db_table = "cc_playout_history_template_field"
|
db_table = "cc_playout_history_template_field"
|
||||||
|
|
||||||
|
|
||||||
class Timestamp(models.Model):
|
|
||||||
timestamp = models.DateTimeField()
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "cc_timestamp"
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
from rest_framework import routers
|
||||||
|
|
||||||
|
from .views import (
|
||||||
|
ListenerCountViewSet,
|
||||||
|
LiveLogViewSet,
|
||||||
|
MountNameViewSet,
|
||||||
|
PlayoutHistoryMetadataViewSet,
|
||||||
|
PlayoutHistoryTemplateFieldViewSet,
|
||||||
|
PlayoutHistoryTemplateViewSet,
|
||||||
|
PlayoutHistoryViewSet,
|
||||||
|
TimestampViewSet,
|
||||||
|
)
|
||||||
|
|
||||||
|
router = routers.DefaultRouter()
|
||||||
|
router.register("listener-counts", ListenerCountViewSet)
|
||||||
|
router.register("live-logs", LiveLogViewSet)
|
||||||
|
router.register("mount-names", MountNameViewSet)
|
||||||
|
router.register("playout-history", PlayoutHistoryViewSet)
|
||||||
|
router.register("playout-history-metadata", PlayoutHistoryMetadataViewSet)
|
||||||
|
router.register("playout-history-templates", PlayoutHistoryTemplateViewSet)
|
||||||
|
router.register("playout-history-template-fields", PlayoutHistoryTemplateFieldViewSet)
|
||||||
|
router.register("timestamps", TimestampViewSet)
|
|
@ -0,0 +1,8 @@
|
||||||
|
from .listener import ListenerCountSerializer, MountNameSerializer, TimestampSerializer
|
||||||
|
from .live import LiveLogSerializer
|
||||||
|
from .played import (
|
||||||
|
PlayoutHistoryMetadataSerializer,
|
||||||
|
PlayoutHistorySerializer,
|
||||||
|
PlayoutHistoryTemplateFieldSerializer,
|
||||||
|
PlayoutHistoryTemplateSerializer,
|
||||||
|
)
|
|
@ -0,0 +1,21 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import ListenerCount, MountName, Timestamp
|
||||||
|
|
||||||
|
|
||||||
|
class MountNameSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = MountName
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class TimestampSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Timestamp
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class ListenerCountSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ListenerCount
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,9 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import LiveLog
|
||||||
|
|
||||||
|
|
||||||
|
class LiveLogSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = LiveLog
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,32 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import (
|
||||||
|
PlayoutHistory,
|
||||||
|
PlayoutHistoryMetadata,
|
||||||
|
PlayoutHistoryTemplate,
|
||||||
|
PlayoutHistoryTemplateField,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PlayoutHistorySerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = PlayoutHistory
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class PlayoutHistoryMetadataSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = PlayoutHistoryMetadata
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class PlayoutHistoryTemplateSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = PlayoutHistoryTemplate
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class PlayoutHistoryTemplateFieldSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = PlayoutHistoryTemplateField
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,8 @@
|
||||||
|
from .listener import ListenerCountViewSet, MountNameViewSet, TimestampViewSet
|
||||||
|
from .live import LiveLogViewSet
|
||||||
|
from .played import (
|
||||||
|
PlayoutHistoryMetadataViewSet,
|
||||||
|
PlayoutHistoryTemplateFieldViewSet,
|
||||||
|
PlayoutHistoryTemplateViewSet,
|
||||||
|
PlayoutHistoryViewSet,
|
||||||
|
)
|
|
@ -0,0 +1,26 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import ListenerCount, MountName, Timestamp
|
||||||
|
from ..serializers import (
|
||||||
|
ListenerCountSerializer,
|
||||||
|
MountNameSerializer,
|
||||||
|
TimestampSerializer,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MountNameViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = MountName.objects.all()
|
||||||
|
serializer_class = MountNameSerializer
|
||||||
|
model_permission_name = "mountname"
|
||||||
|
|
||||||
|
|
||||||
|
class TimestampViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Timestamp.objects.all()
|
||||||
|
serializer_class = TimestampSerializer
|
||||||
|
model_permission_name = "timestamp"
|
||||||
|
|
||||||
|
|
||||||
|
class ListenerCountViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = ListenerCount.objects.all()
|
||||||
|
serializer_class = ListenerCountSerializer
|
||||||
|
model_permission_name = "listenercount"
|
|
@ -0,0 +1,10 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import LiveLog
|
||||||
|
from ..serializers import LiveLogSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class LiveLogViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = LiveLog.objects.all()
|
||||||
|
serializer_class = LiveLogSerializer
|
||||||
|
model_permission_name = "livelog"
|
|
@ -0,0 +1,38 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import (
|
||||||
|
PlayoutHistory,
|
||||||
|
PlayoutHistoryMetadata,
|
||||||
|
PlayoutHistoryTemplate,
|
||||||
|
PlayoutHistoryTemplateField,
|
||||||
|
)
|
||||||
|
from ..serializers import (
|
||||||
|
PlayoutHistoryMetadataSerializer,
|
||||||
|
PlayoutHistorySerializer,
|
||||||
|
PlayoutHistoryTemplateFieldSerializer,
|
||||||
|
PlayoutHistoryTemplateSerializer,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PlayoutHistoryViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = PlayoutHistory.objects.all()
|
||||||
|
serializer_class = PlayoutHistorySerializer
|
||||||
|
model_permission_name = "playouthistory"
|
||||||
|
|
||||||
|
|
||||||
|
class PlayoutHistoryMetadataViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = PlayoutHistoryMetadata.objects.all()
|
||||||
|
serializer_class = PlayoutHistoryMetadataSerializer
|
||||||
|
model_permission_name = "playouthistorymetadata"
|
||||||
|
|
||||||
|
|
||||||
|
class PlayoutHistoryTemplateViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = PlayoutHistoryTemplate.objects.all()
|
||||||
|
serializer_class = PlayoutHistoryTemplateSerializer
|
||||||
|
model_permission_name = "playouthistorytemplate"
|
||||||
|
|
||||||
|
|
||||||
|
class PlayoutHistoryTemplateFieldViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = PlayoutHistoryTemplateField.objects.all()
|
||||||
|
serializer_class = PlayoutHistoryTemplateFieldSerializer
|
||||||
|
model_permission_name = "playouthistorytemplatefield"
|
|
@ -1,12 +1,12 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""Django's command-line utility for administrative tasks."""
|
"""Django's command-line utility for administrative tasks."""
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "libretime_api.settings")
|
"""Run administrative tasks."""
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "libretime_api.settings.prod")
|
||||||
os.environ.setdefault("LIBRETIME_CONFIG_FILEPATH", "/etc/airtime/airtime.conf")
|
os.environ.setdefault("LIBRETIME_CONFIG_FILEPATH", "/etc/airtime/airtime.conf")
|
||||||
try:
|
try:
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
|
@ -1,22 +0,0 @@
|
||||||
from django.contrib.auth.models import BaseUserManager
|
|
||||||
|
|
||||||
|
|
||||||
class UserManager(BaseUserManager):
|
|
||||||
def create_user(self, username, type, email, first_name, last_name, password):
|
|
||||||
user = self.model(
|
|
||||||
username=username,
|
|
||||||
type=type,
|
|
||||||
email=email,
|
|
||||||
first_name=first_name,
|
|
||||||
last_name=last_name,
|
|
||||||
)
|
|
||||||
user.set_password(password)
|
|
||||||
user.save(using=self._db)
|
|
||||||
return user
|
|
||||||
|
|
||||||
def create_superuser(self, username, email, first_name, last_name, password):
|
|
||||||
user = self.create_user(username, "A", email, first_name, last_name, password)
|
|
||||||
return user
|
|
||||||
|
|
||||||
def get_by_natural_key(self, username):
|
|
||||||
return self.get(username=username)
|
|
|
@ -1,14 +0,0 @@
|
||||||
from .authentication import *
|
|
||||||
from .celery import *
|
|
||||||
from .countries import *
|
|
||||||
from .files import *
|
|
||||||
from .playlists import *
|
|
||||||
from .playout import *
|
|
||||||
from .podcasts import *
|
|
||||||
from .preferences import *
|
|
||||||
from .schedule import *
|
|
||||||
from .services import *
|
|
||||||
from .shows import *
|
|
||||||
from .smart_blocks import *
|
|
||||||
from .tracks import *
|
|
||||||
from .webstreams import *
|
|
|
@ -1,26 +0,0 @@
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
from .files import File
|
|
||||||
|
|
||||||
|
|
||||||
class ThirdPartyTrackReference(models.Model):
|
|
||||||
service = models.CharField(max_length=256)
|
|
||||||
foreign_id = models.CharField(unique=True, max_length=256, blank=True, null=True)
|
|
||||||
file = models.ForeignKey(File, models.DO_NOTHING, blank=True, null=True)
|
|
||||||
upload_time = models.DateTimeField(blank=True, null=True)
|
|
||||||
status = models.CharField(max_length=256, blank=True, null=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "third_party_track_references"
|
|
||||||
|
|
||||||
|
|
||||||
class TrackType(models.Model):
|
|
||||||
code = models.CharField(max_length=16, unique=True)
|
|
||||||
type_name = models.CharField(max_length=255, blank=True, null=True)
|
|
||||||
description = models.CharField(max_length=255, blank=True, null=True)
|
|
||||||
visibility = models.BooleanField(blank=True, default=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "cc_track_types"
|
|
|
@ -1,10 +1,4 @@
|
||||||
import logging
|
from .core.models import DJ, GUEST, PROGRAM_MANAGER, USER_TYPES
|
||||||
|
|
||||||
from django.contrib.auth.models import Group, Permission
|
|
||||||
|
|
||||||
from .models.user_constants import DJ, GUEST, PROGRAM_MANAGER, USER_TYPES
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
GUEST_PERMISSIONS = [
|
GUEST_PERMISSIONS = [
|
||||||
"view_schedule",
|
"view_schedule",
|
||||||
|
@ -24,6 +18,7 @@ GUEST_PERMISSIONS = [
|
||||||
"view_webstream",
|
"view_webstream",
|
||||||
"view_apiroot",
|
"view_apiroot",
|
||||||
]
|
]
|
||||||
|
|
||||||
DJ_PERMISSIONS = GUEST_PERMISSIONS + [
|
DJ_PERMISSIONS = GUEST_PERMISSIONS + [
|
||||||
"add_file",
|
"add_file",
|
||||||
"add_podcast",
|
"add_podcast",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from rest_framework.permissions import BasePermission
|
from rest_framework.permissions import BasePermission
|
||||||
|
|
||||||
from .models.user_constants import DJ
|
from .core.models.role import DJ
|
||||||
|
|
||||||
REQUEST_PERMISSION_TYPE_MAP = {
|
REQUEST_PERMISSION_TYPE_MAP = {
|
||||||
"GET": "view",
|
"GET": "view",
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ScheduleConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "libretime_api.schedule"
|
||||||
|
verbose_name = "LibreTime Schedule API"
|
|
@ -0,0 +1,6 @@
|
||||||
|
from .playlist import Playlist, PlaylistContent
|
||||||
|
from .podcast import ImportedPodcast, Podcast, PodcastEpisode, StationPodcast
|
||||||
|
from .schedule import Schedule
|
||||||
|
from .show import Show, ShowDays, ShowHost, ShowInstance, ShowRebroadcast
|
||||||
|
from .smart_block import SmartBlock, SmartBlockContent, SmartBlockCriteria
|
||||||
|
from .webstream import Webstream, WebstreamMetadata
|
|
@ -1,14 +1,11 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from .files import File
|
|
||||||
from .smart_blocks import SmartBlock
|
|
||||||
|
|
||||||
|
|
||||||
class Playlist(models.Model):
|
class Playlist(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
mtime = models.DateTimeField(blank=True, null=True)
|
mtime = models.DateTimeField(blank=True, null=True)
|
||||||
utime = models.DateTimeField(blank=True, null=True)
|
utime = models.DateTimeField(blank=True, null=True)
|
||||||
creator = models.ForeignKey("User", models.DO_NOTHING, blank=True, null=True)
|
creator = models.ForeignKey("core.User", models.DO_NOTHING, blank=True, null=True)
|
||||||
description = models.CharField(max_length=512, blank=True, null=True)
|
description = models.CharField(max_length=512, blank=True, null=True)
|
||||||
length = models.DurationField(blank=True, null=True)
|
length = models.DurationField(blank=True, null=True)
|
||||||
|
|
||||||
|
@ -21,9 +18,9 @@ class Playlist(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class PlaylistContent(models.Model):
|
class PlaylistContent(models.Model):
|
||||||
playlist = models.ForeignKey(Playlist, models.DO_NOTHING, blank=True, null=True)
|
playlist = models.ForeignKey("Playlist", models.DO_NOTHING, blank=True, null=True)
|
||||||
file = models.ForeignKey(File, models.DO_NOTHING, blank=True, null=True)
|
file = models.ForeignKey("storage.File", models.DO_NOTHING, blank=True, null=True)
|
||||||
block = models.ForeignKey(SmartBlock, models.DO_NOTHING, blank=True, null=True)
|
block = models.ForeignKey("SmartBlock", models.DO_NOTHING, blank=True, null=True)
|
||||||
stream_id = models.IntegerField(blank=True, null=True)
|
stream_id = models.IntegerField(blank=True, null=True)
|
||||||
type = models.SmallIntegerField()
|
type = models.SmallIntegerField()
|
||||||
position = models.IntegerField(blank=True, null=True)
|
position = models.IntegerField(blank=True, null=True)
|
|
@ -1,22 +1,5 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from .authentication import User
|
|
||||||
from .files import File
|
|
||||||
|
|
||||||
|
|
||||||
class ImportedPodcast(models.Model):
|
|
||||||
auto_ingest = models.BooleanField()
|
|
||||||
auto_ingest_timestamp = models.DateTimeField(blank=True, null=True)
|
|
||||||
album_override = models.BooleanField()
|
|
||||||
podcast = models.ForeignKey("Podcast", models.DO_NOTHING)
|
|
||||||
|
|
||||||
def get_owner(self):
|
|
||||||
return self.podcast.owner
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "imported_podcast"
|
|
||||||
|
|
||||||
|
|
||||||
class Podcast(models.Model):
|
class Podcast(models.Model):
|
||||||
url = models.CharField(max_length=4096)
|
url = models.CharField(max_length=4096)
|
||||||
|
@ -33,7 +16,7 @@ class Podcast(models.Model):
|
||||||
itunes_category = models.CharField(max_length=4096, blank=True, null=True)
|
itunes_category = models.CharField(max_length=4096, blank=True, null=True)
|
||||||
itunes_explicit = models.CharField(max_length=4096, blank=True, null=True)
|
itunes_explicit = models.CharField(max_length=4096, blank=True, null=True)
|
||||||
owner = models.ForeignKey(
|
owner = models.ForeignKey(
|
||||||
User, models.DO_NOTHING, db_column="owner", blank=True, null=True
|
"core.User", models.DO_NOTHING, db_column="owner", blank=True, null=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_owner(self):
|
def get_owner(self):
|
||||||
|
@ -49,8 +32,8 @@ class Podcast(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class PodcastEpisode(models.Model):
|
class PodcastEpisode(models.Model):
|
||||||
file = models.ForeignKey(File, models.DO_NOTHING, blank=True, null=True)
|
file = models.ForeignKey("storage.File", models.DO_NOTHING, blank=True, null=True)
|
||||||
podcast = models.ForeignKey(Podcast, models.DO_NOTHING)
|
podcast = models.ForeignKey("Podcast", models.DO_NOTHING)
|
||||||
publication_date = models.DateTimeField()
|
publication_date = models.DateTimeField()
|
||||||
download_url = models.CharField(max_length=4096)
|
download_url = models.CharField(max_length=4096)
|
||||||
episode_guid = models.CharField(max_length=4096)
|
episode_guid = models.CharField(max_length=4096)
|
||||||
|
@ -76,7 +59,7 @@ class PodcastEpisode(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class StationPodcast(models.Model):
|
class StationPodcast(models.Model):
|
||||||
podcast = models.ForeignKey(Podcast, models.DO_NOTHING)
|
podcast = models.ForeignKey("Podcast", models.DO_NOTHING)
|
||||||
|
|
||||||
def get_owner(self):
|
def get_owner(self):
|
||||||
return self.podcast.owner
|
return self.podcast.owner
|
||||||
|
@ -84,3 +67,17 @@ class StationPodcast(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
managed = False
|
managed = False
|
||||||
db_table = "station_podcast"
|
db_table = "station_podcast"
|
||||||
|
|
||||||
|
|
||||||
|
class ImportedPodcast(models.Model):
|
||||||
|
auto_ingest = models.BooleanField()
|
||||||
|
auto_ingest_timestamp = models.DateTimeField(blank=True, null=True)
|
||||||
|
album_override = models.BooleanField()
|
||||||
|
podcast = models.ForeignKey("Podcast", models.DO_NOTHING)
|
||||||
|
|
||||||
|
def get_owner(self):
|
||||||
|
return self.podcast.owner
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "imported_podcast"
|
|
@ -1,12 +1,10 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from .files import File
|
|
||||||
|
|
||||||
|
|
||||||
class Schedule(models.Model):
|
class Schedule(models.Model):
|
||||||
starts = models.DateTimeField()
|
starts = models.DateTimeField()
|
||||||
ends = models.DateTimeField()
|
ends = models.DateTimeField()
|
||||||
file = models.ForeignKey(File, models.DO_NOTHING, blank=True, null=True)
|
file = models.ForeignKey("storage.File", models.DO_NOTHING, blank=True, null=True)
|
||||||
stream = models.ForeignKey("Webstream", models.DO_NOTHING, blank=True, null=True)
|
stream = models.ForeignKey("Webstream", models.DO_NOTHING, blank=True, null=True)
|
||||||
clip_length = models.DurationField(blank=True, null=True)
|
clip_length = models.DurationField(blank=True, null=True)
|
||||||
fade_in = models.TimeField(blank=True, null=True)
|
fade_in = models.TimeField(blank=True, null=True)
|
|
@ -1,8 +1,5 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from .files import File
|
|
||||||
from .playlists import Playlist
|
|
||||||
|
|
||||||
|
|
||||||
class Show(models.Model):
|
class Show(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
|
@ -19,7 +16,9 @@ class Show(models.Model):
|
||||||
is_linkable = models.BooleanField()
|
is_linkable = models.BooleanField()
|
||||||
image_path = models.CharField(max_length=255, blank=True, null=True)
|
image_path = models.CharField(max_length=255, blank=True, null=True)
|
||||||
has_autoplaylist = models.BooleanField()
|
has_autoplaylist = models.BooleanField()
|
||||||
autoplaylist = models.ForeignKey(Playlist, models.DO_NOTHING, blank=True, null=True)
|
autoplaylist = models.ForeignKey(
|
||||||
|
"Playlist", models.DO_NOTHING, blank=True, null=True
|
||||||
|
)
|
||||||
autoplaylist_repeat = models.BooleanField()
|
autoplaylist_repeat = models.BooleanField()
|
||||||
|
|
||||||
def get_owner(self):
|
def get_owner(self):
|
||||||
|
@ -39,7 +38,7 @@ class ShowDays(models.Model):
|
||||||
day = models.SmallIntegerField(blank=True, null=True)
|
day = models.SmallIntegerField(blank=True, null=True)
|
||||||
repeat_type = models.SmallIntegerField()
|
repeat_type = models.SmallIntegerField()
|
||||||
next_pop_date = models.DateField(blank=True, null=True)
|
next_pop_date = models.DateField(blank=True, null=True)
|
||||||
show = models.ForeignKey(Show, models.DO_NOTHING)
|
show = models.ForeignKey("Show", models.DO_NOTHING)
|
||||||
record = models.SmallIntegerField(blank=True, null=True)
|
record = models.SmallIntegerField(blank=True, null=True)
|
||||||
|
|
||||||
def get_owner(self):
|
def get_owner(self):
|
||||||
|
@ -51,8 +50,8 @@ class ShowDays(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class ShowHost(models.Model):
|
class ShowHost(models.Model):
|
||||||
show = models.ForeignKey(Show, models.DO_NOTHING)
|
show = models.ForeignKey("Show", models.DO_NOTHING)
|
||||||
subjs = models.ForeignKey("User", models.DO_NOTHING)
|
subjs = models.ForeignKey("core.User", models.DO_NOTHING)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
managed = False
|
managed = False
|
||||||
|
@ -63,11 +62,11 @@ class ShowInstance(models.Model):
|
||||||
description = models.CharField(max_length=8192, blank=True, null=True)
|
description = models.CharField(max_length=8192, blank=True, null=True)
|
||||||
starts = models.DateTimeField()
|
starts = models.DateTimeField()
|
||||||
ends = models.DateTimeField()
|
ends = models.DateTimeField()
|
||||||
show = models.ForeignKey(Show, models.DO_NOTHING)
|
show = models.ForeignKey("Show", models.DO_NOTHING)
|
||||||
record = models.SmallIntegerField(blank=True, null=True)
|
record = models.SmallIntegerField(blank=True, null=True)
|
||||||
rebroadcast = models.SmallIntegerField(blank=True, null=True)
|
rebroadcast = models.SmallIntegerField(blank=True, null=True)
|
||||||
instance = models.ForeignKey("self", models.DO_NOTHING, blank=True, null=True)
|
instance = models.ForeignKey("self", models.DO_NOTHING, blank=True, null=True)
|
||||||
file = models.ForeignKey(File, models.DO_NOTHING, blank=True, null=True)
|
file = models.ForeignKey("storage.File", models.DO_NOTHING, blank=True, null=True)
|
||||||
time_filled = models.DurationField(blank=True, null=True)
|
time_filled = models.DurationField(blank=True, null=True)
|
||||||
created = models.DateTimeField()
|
created = models.DateTimeField()
|
||||||
last_scheduled = models.DateTimeField(blank=True, null=True)
|
last_scheduled = models.DateTimeField(blank=True, null=True)
|
||||||
|
@ -85,7 +84,7 @@ class ShowInstance(models.Model):
|
||||||
class ShowRebroadcast(models.Model):
|
class ShowRebroadcast(models.Model):
|
||||||
day_offset = models.CharField(max_length=1024)
|
day_offset = models.CharField(max_length=1024)
|
||||||
start_time = models.TimeField()
|
start_time = models.TimeField()
|
||||||
show = models.ForeignKey(Show, models.DO_NOTHING)
|
show = models.ForeignKey("Show", models.DO_NOTHING)
|
||||||
|
|
||||||
def get_owner(self):
|
def get_owner(self):
|
||||||
return show.get_owner()
|
return show.get_owner()
|
|
@ -5,7 +5,7 @@ class SmartBlock(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
mtime = models.DateTimeField(blank=True, null=True)
|
mtime = models.DateTimeField(blank=True, null=True)
|
||||||
utime = models.DateTimeField(blank=True, null=True)
|
utime = models.DateTimeField(blank=True, null=True)
|
||||||
creator = models.ForeignKey("User", models.DO_NOTHING, blank=True, null=True)
|
creator = models.ForeignKey("core.User", models.DO_NOTHING, blank=True, null=True)
|
||||||
description = models.CharField(max_length=512, blank=True, null=True)
|
description = models.CharField(max_length=512, blank=True, null=True)
|
||||||
length = models.DurationField(blank=True, null=True)
|
length = models.DurationField(blank=True, null=True)
|
||||||
type = models.CharField(max_length=7, blank=True, null=True)
|
type = models.CharField(max_length=7, blank=True, null=True)
|
||||||
|
@ -29,8 +29,8 @@ class SmartBlock(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class SmartBlockContent(models.Model):
|
class SmartBlockContent(models.Model):
|
||||||
block = models.ForeignKey(SmartBlock, models.DO_NOTHING, blank=True, null=True)
|
block = models.ForeignKey("SmartBlock", models.DO_NOTHING, blank=True, null=True)
|
||||||
file = models.ForeignKey("File", models.DO_NOTHING, blank=True, null=True)
|
file = models.ForeignKey("storage.File", models.DO_NOTHING, blank=True, null=True)
|
||||||
position = models.IntegerField(blank=True, null=True)
|
position = models.IntegerField(blank=True, null=True)
|
||||||
trackoffset = models.FloatField()
|
trackoffset = models.FloatField()
|
||||||
cliplength = models.DurationField(blank=True, null=True)
|
cliplength = models.DurationField(blank=True, null=True)
|
||||||
|
@ -63,7 +63,7 @@ class SmartBlockCriteria(models.Model):
|
||||||
value = models.CharField(max_length=512)
|
value = models.CharField(max_length=512)
|
||||||
extra = models.CharField(max_length=512, blank=True, null=True)
|
extra = models.CharField(max_length=512, blank=True, null=True)
|
||||||
criteriagroup = models.IntegerField(blank=True, null=True)
|
criteriagroup = models.IntegerField(blank=True, null=True)
|
||||||
block = models.ForeignKey(SmartBlock, models.DO_NOTHING)
|
block = models.ForeignKey("SmartBlock", models.DO_NOTHING)
|
||||||
|
|
||||||
def get_owner(self):
|
def get_owner(self):
|
||||||
return self.block.get_owner()
|
return self.block.get_owner()
|
|
@ -1,8 +1,6 @@
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from .schedule import Schedule
|
|
||||||
|
|
||||||
|
|
||||||
class Webstream(models.Model):
|
class Webstream(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
|
@ -29,7 +27,7 @@ class Webstream(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class WebstreamMetadata(models.Model):
|
class WebstreamMetadata(models.Model):
|
||||||
instance = models.ForeignKey(Schedule, models.DO_NOTHING)
|
instance = models.ForeignKey("Schedule", models.DO_NOTHING)
|
||||||
start_time = models.DateTimeField()
|
start_time = models.DateTimeField()
|
||||||
liquidsoap_data = models.CharField(max_length=1024)
|
liquidsoap_data = models.CharField(max_length=1024)
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
from rest_framework import routers
|
||||||
|
|
||||||
|
from .views import (
|
||||||
|
ImportedPodcastViewSet,
|
||||||
|
PlaylistContentViewSet,
|
||||||
|
PlaylistViewSet,
|
||||||
|
PodcastEpisodeViewSet,
|
||||||
|
PodcastViewSet,
|
||||||
|
ScheduleViewSet,
|
||||||
|
ShowDaysViewSet,
|
||||||
|
ShowHostViewSet,
|
||||||
|
ShowInstanceViewSet,
|
||||||
|
ShowRebroadcastViewSet,
|
||||||
|
ShowViewSet,
|
||||||
|
SmartBlockContentViewSet,
|
||||||
|
SmartBlockCriteriaViewSet,
|
||||||
|
SmartBlockViewSet,
|
||||||
|
StationPodcastViewSet,
|
||||||
|
WebstreamMetadataViewSet,
|
||||||
|
WebstreamViewSet,
|
||||||
|
)
|
||||||
|
|
||||||
|
router = routers.DefaultRouter()
|
||||||
|
router.register("playlist-contents", PlaylistContentViewSet)
|
||||||
|
router.register("playlists", PlaylistViewSet)
|
||||||
|
router.register("podcast-episodes", PodcastEpisodeViewSet)
|
||||||
|
router.register("podcasts", PodcastViewSet)
|
||||||
|
router.register("station-podcasts", StationPodcastViewSet)
|
||||||
|
router.register("imported-podcasts", ImportedPodcastViewSet)
|
||||||
|
router.register("schedule", ScheduleViewSet)
|
||||||
|
router.register("show-days", ShowDaysViewSet)
|
||||||
|
router.register("show-hosts", ShowHostViewSet)
|
||||||
|
router.register("show-instances", ShowInstanceViewSet)
|
||||||
|
router.register("show-rebroadcasts", ShowRebroadcastViewSet)
|
||||||
|
router.register("shows", ShowViewSet)
|
||||||
|
router.register("smart-block-contents", SmartBlockContentViewSet)
|
||||||
|
router.register("smart-block-criteria", SmartBlockCriteriaViewSet)
|
||||||
|
router.register("smart-blocks", SmartBlockViewSet)
|
||||||
|
router.register("webstream-metadata", WebstreamMetadataViewSet)
|
||||||
|
router.register("webstreams", WebstreamViewSet)
|
|
@ -0,0 +1,21 @@
|
||||||
|
from .playlist import PlaylistContentSerializer, PlaylistSerializer
|
||||||
|
from .podcast import (
|
||||||
|
ImportedPodcastSerializer,
|
||||||
|
PodcastEpisodeSerializer,
|
||||||
|
PodcastSerializer,
|
||||||
|
StationPodcastSerializer,
|
||||||
|
)
|
||||||
|
from .schedule import ScheduleSerializer
|
||||||
|
from .show import (
|
||||||
|
ShowDaysSerializer,
|
||||||
|
ShowHostSerializer,
|
||||||
|
ShowInstanceSerializer,
|
||||||
|
ShowRebroadcastSerializer,
|
||||||
|
ShowSerializer,
|
||||||
|
)
|
||||||
|
from .smart_block import (
|
||||||
|
SmartBlockContentSerializer,
|
||||||
|
SmartBlockCriteriaSerializer,
|
||||||
|
SmartBlockSerializer,
|
||||||
|
)
|
||||||
|
from .webstream import WebstreamMetadataSerializer, WebstreamSerializer
|
|
@ -0,0 +1,15 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import Playlist, PlaylistContent
|
||||||
|
|
||||||
|
|
||||||
|
class PlaylistSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Playlist
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class PlaylistContentSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = PlaylistContent
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,27 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import ImportedPodcast, Podcast, PodcastEpisode, StationPodcast
|
||||||
|
|
||||||
|
|
||||||
|
class PodcastSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Podcast
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class PodcastEpisodeSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = PodcastEpisode
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class StationPodcastSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = StationPodcast
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class ImportedPodcastSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ImportedPodcast
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,35 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import Schedule
|
||||||
|
|
||||||
|
|
||||||
|
class ScheduleSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
file_id = serializers.IntegerField(source="file.id", read_only=True)
|
||||||
|
stream_id = serializers.IntegerField(source="stream.id", read_only=True)
|
||||||
|
instance_id = serializers.IntegerField(source="instance.id", read_only=True)
|
||||||
|
cue_out = serializers.DurationField(source="get_cueout", read_only=True)
|
||||||
|
ends = serializers.DateTimeField(source="get_ends", read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Schedule
|
||||||
|
fields = [
|
||||||
|
"item_url",
|
||||||
|
"id",
|
||||||
|
"starts",
|
||||||
|
"ends",
|
||||||
|
"file",
|
||||||
|
"file_id",
|
||||||
|
"stream",
|
||||||
|
"stream_id",
|
||||||
|
"clip_length",
|
||||||
|
"fade_in",
|
||||||
|
"fade_out",
|
||||||
|
"cue_in",
|
||||||
|
"cue_out",
|
||||||
|
"media_item_played",
|
||||||
|
"instance",
|
||||||
|
"instance_id",
|
||||||
|
"playout_status",
|
||||||
|
"broadcasted",
|
||||||
|
"position",
|
||||||
|
]
|
|
@ -0,0 +1,69 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import Show, ShowDays, ShowHost, ShowInstance, ShowRebroadcast
|
||||||
|
|
||||||
|
|
||||||
|
class ShowSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Show
|
||||||
|
fields = [
|
||||||
|
"item_url",
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"url",
|
||||||
|
"genre",
|
||||||
|
"description",
|
||||||
|
"color",
|
||||||
|
"background_color",
|
||||||
|
"linked",
|
||||||
|
"is_linkable",
|
||||||
|
"image_path",
|
||||||
|
"has_autoplaylist",
|
||||||
|
"autoplaylist_repeat",
|
||||||
|
"autoplaylist",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ShowDaysSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ShowDays
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class ShowHostSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ShowHost
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class ShowInstanceSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
show_id = serializers.IntegerField(source="show.id", read_only=True)
|
||||||
|
file_id = serializers.IntegerField(source="file.id", read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ShowInstance
|
||||||
|
fields = [
|
||||||
|
"item_url",
|
||||||
|
"id",
|
||||||
|
"description",
|
||||||
|
"starts",
|
||||||
|
"ends",
|
||||||
|
"record",
|
||||||
|
"rebroadcast",
|
||||||
|
"time_filled",
|
||||||
|
"created",
|
||||||
|
"last_scheduled",
|
||||||
|
"modified_instance",
|
||||||
|
"autoplaylist_built",
|
||||||
|
"show",
|
||||||
|
"show_id",
|
||||||
|
"instance",
|
||||||
|
"file",
|
||||||
|
"file_id",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ShowRebroadcastSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ShowRebroadcast
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,21 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import SmartBlock, SmartBlockContent, SmartBlockCriteria
|
||||||
|
|
||||||
|
|
||||||
|
class SmartBlockSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = SmartBlock
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class SmartBlockContentSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = SmartBlockContent
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class SmartBlockCriteriaSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = SmartBlockCriteria
|
||||||
|
fields = "__all__"
|
|
@ -0,0 +1,17 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from ..models import Webstream, WebstreamMetadata
|
||||||
|
|
||||||
|
|
||||||
|
class WebstreamSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
id = serializers.IntegerField(read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Webstream
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class WebstreamMetadataSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = WebstreamMetadata
|
||||||
|
fields = "__all__"
|
|
@ -2,7 +2,7 @@ from datetime import datetime, timedelta
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from libretime_api.models import Schedule, ShowInstance
|
from ...models import Schedule, ShowInstance
|
||||||
|
|
||||||
|
|
||||||
class TestSchedule(TestCase):
|
class TestSchedule(TestCase):
|
|
@ -2,47 +2,11 @@ import os
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import AnonymousUser
|
|
||||||
from django.utils import dateparse
|
from django.utils import dateparse
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
from rest_framework.test import APIRequestFactory, APITestCase
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
from libretime_api.views import FileViewSet
|
from ...._fixtures import AUDIO_FILENAME, fixture_path
|
||||||
|
|
||||||
|
|
||||||
class TestFileViewSet(APITestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpTestData(cls):
|
|
||||||
cls.path = "/api/v2/files/{id}/download/"
|
|
||||||
cls.token = settings.CONFIG.general.api_key
|
|
||||||
|
|
||||||
def test_invalid(self):
|
|
||||||
path = self.path.format(id="a")
|
|
||||||
self.client.credentials(HTTP_AUTHORIZATION=f"Api-Key {self.token}")
|
|
||||||
response = self.client.get(path)
|
|
||||||
self.assertEqual(response.status_code, 400)
|
|
||||||
|
|
||||||
def test_does_not_exist(self):
|
|
||||||
path = self.path.format(id="1")
|
|
||||||
self.client.credentials(HTTP_AUTHORIZATION=f"Api-Key {self.token}")
|
|
||||||
response = self.client.get(path)
|
|
||||||
self.assertEqual(response.status_code, 404)
|
|
||||||
|
|
||||||
def test_exists(self):
|
|
||||||
music_dir = baker.make(
|
|
||||||
"libretime_api.MusicDir",
|
|
||||||
directory=os.path.join(os.path.dirname(__file__), "resources"),
|
|
||||||
)
|
|
||||||
f = baker.make(
|
|
||||||
"libretime_api.File",
|
|
||||||
directory=music_dir,
|
|
||||||
mime="audio/mp3",
|
|
||||||
filepath="song.mp3",
|
|
||||||
)
|
|
||||||
path = self.path.format(id=str(f.pk))
|
|
||||||
self.client.credentials(HTTP_AUTHORIZATION=f"Api-Key {self.token}")
|
|
||||||
response = self.client.get(path)
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
|
|
||||||
class TestScheduleViewSet(APITestCase):
|
class TestScheduleViewSet(APITestCase):
|
||||||
|
@ -53,25 +17,25 @@ class TestScheduleViewSet(APITestCase):
|
||||||
|
|
||||||
def test_schedule_item_full_length(self):
|
def test_schedule_item_full_length(self):
|
||||||
music_dir = baker.make(
|
music_dir = baker.make(
|
||||||
"libretime_api.MusicDir",
|
"storage.MusicDir",
|
||||||
directory=os.path.join(os.path.dirname(__file__), "resources"),
|
directory=str(fixture_path),
|
||||||
)
|
)
|
||||||
f = baker.make(
|
f = baker.make(
|
||||||
"libretime_api.File",
|
"storage.File",
|
||||||
directory=music_dir,
|
directory=music_dir,
|
||||||
mime="audio/mp3",
|
mime="audio/mp3",
|
||||||
filepath="song.mp3",
|
filepath=AUDIO_FILENAME,
|
||||||
length=timedelta(seconds=40.86),
|
length=timedelta(seconds=40.86),
|
||||||
cuein=timedelta(seconds=0),
|
cuein=timedelta(seconds=0),
|
||||||
cueout=timedelta(seconds=40.8131),
|
cueout=timedelta(seconds=40.8131),
|
||||||
)
|
)
|
||||||
show = baker.make(
|
show = baker.make(
|
||||||
"libretime_api.ShowInstance",
|
"schedule.ShowInstance",
|
||||||
starts=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
starts=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
||||||
ends=datetime.now(tz=timezone.utc) + timedelta(minutes=5),
|
ends=datetime.now(tz=timezone.utc) + timedelta(minutes=5),
|
||||||
)
|
)
|
||||||
scheduleItem = baker.make(
|
scheduleItem = baker.make(
|
||||||
"libretime_api.Schedule",
|
"schedule.Schedule",
|
||||||
starts=datetime.now(tz=timezone.utc),
|
starts=datetime.now(tz=timezone.utc),
|
||||||
ends=datetime.now(tz=timezone.utc) + f.length,
|
ends=datetime.now(tz=timezone.utc) + f.length,
|
||||||
cue_out=f.cueout,
|
cue_out=f.cueout,
|
||||||
|
@ -87,25 +51,25 @@ class TestScheduleViewSet(APITestCase):
|
||||||
|
|
||||||
def test_schedule_item_trunc(self):
|
def test_schedule_item_trunc(self):
|
||||||
music_dir = baker.make(
|
music_dir = baker.make(
|
||||||
"libretime_api.MusicDir",
|
"storage.MusicDir",
|
||||||
directory=os.path.join(os.path.dirname(__file__), "resources"),
|
directory=str(fixture_path),
|
||||||
)
|
)
|
||||||
f = baker.make(
|
f = baker.make(
|
||||||
"libretime_api.File",
|
"storage.File",
|
||||||
directory=music_dir,
|
directory=music_dir,
|
||||||
mime="audio/mp3",
|
mime="audio/mp3",
|
||||||
filepath="song.mp3",
|
filepath=AUDIO_FILENAME,
|
||||||
length=timedelta(seconds=40.86),
|
length=timedelta(seconds=40.86),
|
||||||
cuein=timedelta(seconds=0),
|
cuein=timedelta(seconds=0),
|
||||||
cueout=timedelta(seconds=40.8131),
|
cueout=timedelta(seconds=40.8131),
|
||||||
)
|
)
|
||||||
show = baker.make(
|
show = baker.make(
|
||||||
"libretime_api.ShowInstance",
|
"schedule.ShowInstance",
|
||||||
starts=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
starts=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
||||||
ends=datetime.now(tz=timezone.utc) + timedelta(seconds=20),
|
ends=datetime.now(tz=timezone.utc) + timedelta(seconds=20),
|
||||||
)
|
)
|
||||||
scheduleItem = baker.make(
|
scheduleItem = baker.make(
|
||||||
"libretime_api.Schedule",
|
"schedule.Schedule",
|
||||||
starts=datetime.now(tz=timezone.utc),
|
starts=datetime.now(tz=timezone.utc),
|
||||||
ends=datetime.now(tz=timezone.utc) + f.length,
|
ends=datetime.now(tz=timezone.utc) + f.length,
|
||||||
instance=show,
|
instance=show,
|
||||||
|
@ -124,33 +88,33 @@ class TestScheduleViewSet(APITestCase):
|
||||||
|
|
||||||
def test_schedule_item_invalid(self):
|
def test_schedule_item_invalid(self):
|
||||||
music_dir = baker.make(
|
music_dir = baker.make(
|
||||||
"libretime_api.MusicDir",
|
"storage.MusicDir",
|
||||||
directory=os.path.join(os.path.dirname(__file__), "resources"),
|
directory=str(fixture_path),
|
||||||
)
|
)
|
||||||
f = baker.make(
|
f = baker.make(
|
||||||
"libretime_api.File",
|
"storage.File",
|
||||||
directory=music_dir,
|
directory=music_dir,
|
||||||
mime="audio/mp3",
|
mime="audio/mp3",
|
||||||
filepath="song.mp3",
|
filepath=AUDIO_FILENAME,
|
||||||
length=timedelta(seconds=40.86),
|
length=timedelta(seconds=40.86),
|
||||||
cuein=timedelta(seconds=0),
|
cuein=timedelta(seconds=0),
|
||||||
cueout=timedelta(seconds=40.8131),
|
cueout=timedelta(seconds=40.8131),
|
||||||
)
|
)
|
||||||
show = baker.make(
|
show = baker.make(
|
||||||
"libretime_api.ShowInstance",
|
"schedule.ShowInstance",
|
||||||
starts=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
starts=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
||||||
ends=datetime.now(tz=timezone.utc) + timedelta(minutes=5),
|
ends=datetime.now(tz=timezone.utc) + timedelta(minutes=5),
|
||||||
)
|
)
|
||||||
scheduleItem = baker.make(
|
schedule_item = baker.make(
|
||||||
"libretime_api.Schedule",
|
"schedule.Schedule",
|
||||||
starts=datetime.now(tz=timezone.utc),
|
starts=datetime.now(tz=timezone.utc),
|
||||||
ends=datetime.now(tz=timezone.utc) + f.length,
|
ends=datetime.now(tz=timezone.utc) + f.length,
|
||||||
cue_out=f.cueout,
|
cue_out=f.cueout,
|
||||||
instance=show,
|
instance=show,
|
||||||
file=f,
|
file=f,
|
||||||
)
|
)
|
||||||
invalidScheduleItem = baker.make(
|
invalid_schedule_item = baker.make(
|
||||||
"libretime_api.Schedule",
|
"schedule.Schedule",
|
||||||
starts=show.ends + timedelta(minutes=1),
|
starts=show.ends + timedelta(minutes=1),
|
||||||
ends=show.ends + timedelta(minutes=1) + f.length,
|
ends=show.ends + timedelta(minutes=1) + f.length,
|
||||||
cue_out=f.cueout,
|
cue_out=f.cueout,
|
||||||
|
@ -163,19 +127,21 @@ class TestScheduleViewSet(APITestCase):
|
||||||
result = response.json()
|
result = response.json()
|
||||||
# The invalid item should be filtered out and not returned
|
# The invalid item should be filtered out and not returned
|
||||||
self.assertEqual(len(result), 1)
|
self.assertEqual(len(result), 1)
|
||||||
self.assertEqual(dateparse.parse_datetime(result[0]["ends"]), scheduleItem.ends)
|
self.assertEqual(
|
||||||
|
dateparse.parse_datetime(result[0]["ends"]), schedule_item.ends
|
||||||
|
)
|
||||||
self.assertEqual(dateparse.parse_duration(result[0]["cue_out"]), f.cueout)
|
self.assertEqual(dateparse.parse_duration(result[0]["cue_out"]), f.cueout)
|
||||||
|
|
||||||
def test_schedule_item_range(self):
|
def test_schedule_item_range(self):
|
||||||
music_dir = baker.make(
|
music_dir = baker.make(
|
||||||
"libretime_api.MusicDir",
|
"storage.MusicDir",
|
||||||
directory=os.path.join(os.path.dirname(__file__), "resources"),
|
directory=str(fixture_path),
|
||||||
)
|
)
|
||||||
f = baker.make(
|
f = baker.make(
|
||||||
"libretime_api.File",
|
"storage.File",
|
||||||
directory=music_dir,
|
directory=music_dir,
|
||||||
mime="audio/mp3",
|
mime="audio/mp3",
|
||||||
filepath="song.mp3",
|
filepath=AUDIO_FILENAME,
|
||||||
length=timedelta(seconds=40.86),
|
length=timedelta(seconds=40.86),
|
||||||
cuein=timedelta(seconds=0),
|
cuein=timedelta(seconds=0),
|
||||||
cueout=timedelta(seconds=40.8131),
|
cueout=timedelta(seconds=40.8131),
|
||||||
|
@ -183,12 +149,12 @@ class TestScheduleViewSet(APITestCase):
|
||||||
filter_point = datetime.now(tz=timezone.utc)
|
filter_point = datetime.now(tz=timezone.utc)
|
||||||
|
|
||||||
show = baker.make(
|
show = baker.make(
|
||||||
"libretime_api.ShowInstance",
|
"schedule.ShowInstance",
|
||||||
starts=filter_point - timedelta(minutes=5),
|
starts=filter_point - timedelta(minutes=5),
|
||||||
ends=filter_point + timedelta(minutes=5),
|
ends=filter_point + timedelta(minutes=5),
|
||||||
)
|
)
|
||||||
schedule_item = baker.make(
|
schedule_item = baker.make(
|
||||||
"libretime_api.Schedule",
|
"schedule.Schedule",
|
||||||
starts=filter_point,
|
starts=filter_point,
|
||||||
ends=filter_point + f.length,
|
ends=filter_point + f.length,
|
||||||
cue_out=f.cueout,
|
cue_out=f.cueout,
|
||||||
|
@ -196,7 +162,7 @@ class TestScheduleViewSet(APITestCase):
|
||||||
file=f,
|
file=f,
|
||||||
)
|
)
|
||||||
previous_item = baker.make(
|
previous_item = baker.make(
|
||||||
"libretime_api.Schedule",
|
"schedule.Schedule",
|
||||||
starts=filter_point - timedelta(minutes=5),
|
starts=filter_point - timedelta(minutes=5),
|
||||||
ends=filter_point - timedelta(minutes=5) + f.length,
|
ends=filter_point - timedelta(minutes=5) + f.length,
|
||||||
cue_out=f.cueout,
|
cue_out=f.cueout,
|
|
@ -0,0 +1,21 @@
|
||||||
|
from .playlist import PlaylistContentViewSet, PlaylistViewSet
|
||||||
|
from .podcast import (
|
||||||
|
ImportedPodcastViewSet,
|
||||||
|
PodcastEpisodeViewSet,
|
||||||
|
PodcastViewSet,
|
||||||
|
StationPodcastViewSet,
|
||||||
|
)
|
||||||
|
from .schedule import ScheduleViewSet
|
||||||
|
from .show import (
|
||||||
|
ShowDaysViewSet,
|
||||||
|
ShowHostViewSet,
|
||||||
|
ShowInstanceViewSet,
|
||||||
|
ShowRebroadcastViewSet,
|
||||||
|
ShowViewSet,
|
||||||
|
)
|
||||||
|
from .smart_block import (
|
||||||
|
SmartBlockContentViewSet,
|
||||||
|
SmartBlockCriteriaViewSet,
|
||||||
|
SmartBlockViewSet,
|
||||||
|
)
|
||||||
|
from .webstream import WebstreamMetadataViewSet, WebstreamViewSet
|
|
@ -0,0 +1,16 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import Playlist, PlaylistContent
|
||||||
|
from ..serializers import PlaylistContentSerializer, PlaylistSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class PlaylistViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Playlist.objects.all()
|
||||||
|
serializer_class = PlaylistSerializer
|
||||||
|
model_permission_name = "playlist"
|
||||||
|
|
||||||
|
|
||||||
|
class PlaylistContentViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = PlaylistContent.objects.all()
|
||||||
|
serializer_class = PlaylistContentSerializer
|
||||||
|
model_permission_name = "playlistcontent"
|
|
@ -0,0 +1,33 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import ImportedPodcast, Podcast, PodcastEpisode, StationPodcast
|
||||||
|
from ..serializers import (
|
||||||
|
ImportedPodcastSerializer,
|
||||||
|
PodcastEpisodeSerializer,
|
||||||
|
PodcastSerializer,
|
||||||
|
StationPodcastSerializer,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PodcastViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Podcast.objects.all()
|
||||||
|
serializer_class = PodcastSerializer
|
||||||
|
model_permission_name = "podcast"
|
||||||
|
|
||||||
|
|
||||||
|
class PodcastEpisodeViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = PodcastEpisode.objects.all()
|
||||||
|
serializer_class = PodcastEpisodeSerializer
|
||||||
|
model_permission_name = "podcastepisode"
|
||||||
|
|
||||||
|
|
||||||
|
class StationPodcastViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = StationPodcast.objects.all()
|
||||||
|
serializer_class = StationPodcastSerializer
|
||||||
|
model_permission_name = "station"
|
||||||
|
|
||||||
|
|
||||||
|
class ImportedPodcastViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = ImportedPodcast.objects.all()
|
||||||
|
serializer_class = ImportedPodcastSerializer
|
||||||
|
model_permission_name = "importedpodcast"
|
|
@ -0,0 +1,41 @@
|
||||||
|
from django.db.models import F
|
||||||
|
from drf_spectacular.utils import OpenApiParameter, extend_schema, extend_schema_view
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..._constants import FILTER_NUMERICAL_LOOKUPS
|
||||||
|
from ..models import Schedule
|
||||||
|
from ..serializers import ScheduleSerializer
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_view(
|
||||||
|
list=extend_schema(
|
||||||
|
parameters=[
|
||||||
|
OpenApiParameter(
|
||||||
|
name="is_valid",
|
||||||
|
description="Filter on valid instances",
|
||||||
|
required=False,
|
||||||
|
type=bool,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
class ScheduleViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Schedule.objects.all()
|
||||||
|
serializer_class = ScheduleSerializer
|
||||||
|
filter_fields = {
|
||||||
|
"starts": FILTER_NUMERICAL_LOOKUPS,
|
||||||
|
"ends": FILTER_NUMERICAL_LOOKUPS,
|
||||||
|
"playout_status": FILTER_NUMERICAL_LOOKUPS,
|
||||||
|
"broadcasted": FILTER_NUMERICAL_LOOKUPS,
|
||||||
|
}
|
||||||
|
model_permission_name = "schedule"
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
filter_valid = self.request.query_params.get("is_valid")
|
||||||
|
if filter_valid is None:
|
||||||
|
return self.queryset.all()
|
||||||
|
filter_valid = filter_valid.strip().lower() in ("true", "yes", "1")
|
||||||
|
if filter_valid:
|
||||||
|
return self.queryset.filter(starts__lt=F("instance__ends"))
|
||||||
|
else:
|
||||||
|
return self.queryset.filter(starts__gte=F("instance__ends"))
|
|
@ -0,0 +1,40 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import Show, ShowDays, ShowHost, ShowInstance, ShowRebroadcast
|
||||||
|
from ..serializers import (
|
||||||
|
ShowDaysSerializer,
|
||||||
|
ShowHostSerializer,
|
||||||
|
ShowInstanceSerializer,
|
||||||
|
ShowRebroadcastSerializer,
|
||||||
|
ShowSerializer,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ShowViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Show.objects.all()
|
||||||
|
serializer_class = ShowSerializer
|
||||||
|
model_permission_name = "show"
|
||||||
|
|
||||||
|
|
||||||
|
class ShowDaysViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = ShowDays.objects.all()
|
||||||
|
serializer_class = ShowDaysSerializer
|
||||||
|
model_permission_name = "showdays"
|
||||||
|
|
||||||
|
|
||||||
|
class ShowHostViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = ShowHost.objects.all()
|
||||||
|
serializer_class = ShowHostSerializer
|
||||||
|
model_permission_name = "showhost"
|
||||||
|
|
||||||
|
|
||||||
|
class ShowInstanceViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = ShowInstance.objects.all()
|
||||||
|
serializer_class = ShowInstanceSerializer
|
||||||
|
model_permission_name = "showinstance"
|
||||||
|
|
||||||
|
|
||||||
|
class ShowRebroadcastViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = ShowRebroadcast.objects.all()
|
||||||
|
serializer_class = ShowRebroadcastSerializer
|
||||||
|
model_permission_name = "showrebroadcast"
|
|
@ -0,0 +1,26 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import SmartBlock, SmartBlockContent, SmartBlockCriteria
|
||||||
|
from ..serializers import (
|
||||||
|
SmartBlockContentSerializer,
|
||||||
|
SmartBlockCriteriaSerializer,
|
||||||
|
SmartBlockSerializer,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SmartBlockViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = SmartBlock.objects.all()
|
||||||
|
serializer_class = SmartBlockSerializer
|
||||||
|
model_permission_name = "smartblock"
|
||||||
|
|
||||||
|
|
||||||
|
class SmartBlockContentViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = SmartBlockContent.objects.all()
|
||||||
|
serializer_class = SmartBlockContentSerializer
|
||||||
|
model_permission_name = "smartblockcontent"
|
||||||
|
|
||||||
|
|
||||||
|
class SmartBlockCriteriaViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = SmartBlockCriteria.objects.all()
|
||||||
|
serializer_class = SmartBlockCriteriaSerializer
|
||||||
|
model_permission_name = "smartblockcriteria"
|
|
@ -0,0 +1,16 @@
|
||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from ..models import Webstream, WebstreamMetadata
|
||||||
|
from ..serializers import WebstreamMetadataSerializer, WebstreamSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class WebstreamViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Webstream.objects.all()
|
||||||
|
serializer_class = WebstreamSerializer
|
||||||
|
model_permission_name = "webstream"
|
||||||
|
|
||||||
|
|
||||||
|
class WebstreamMetadataViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = WebstreamMetadata.objects.all()
|
||||||
|
serializer_class = WebstreamMetadataSerializer
|
||||||
|
model_permission_name = "webstreametadata"
|
|
@ -1,316 +0,0 @@
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
from rest_framework import serializers
|
|
||||||
|
|
||||||
from .models import *
|
|
||||||
|
|
||||||
|
|
||||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = get_user_model()
|
|
||||||
fields = [
|
|
||||||
"item_url",
|
|
||||||
"username",
|
|
||||||
"type",
|
|
||||||
"first_name",
|
|
||||||
"last_name",
|
|
||||||
"lastfail",
|
|
||||||
"skype_contact",
|
|
||||||
"jabber_contact",
|
|
||||||
"email",
|
|
||||||
"cell_phone",
|
|
||||||
"login_attempts",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class SmartBlockSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = SmartBlock
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class SmartBlockContentSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = SmartBlockContent
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class SmartBlockCriteriaSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = SmartBlockCriteria
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class CountrySerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Country
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class FileSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
id = serializers.IntegerField(read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = File
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class ListenerCountSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = ListenerCount
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class LiveLogSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = LiveLog
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class LoginAttemptSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = LoginAttempt
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class MountNameSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = MountName
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class MusicDirSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = MusicDir
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class PlaylistSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Playlist
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class PlaylistContentSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = PlaylistContent
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class PlayoutHistorySerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = PlayoutHistory
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class PlayoutHistoryMetadataSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = PlayoutHistoryMetadata
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class PlayoutHistoryTemplateSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = PlayoutHistoryTemplate
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class PlayoutHistoryTemplateFieldSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = PlayoutHistoryTemplateField
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class PreferenceSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Preference
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class ScheduleSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
file_id = serializers.IntegerField(source="file.id", read_only=True)
|
|
||||||
stream_id = serializers.IntegerField(source="stream.id", read_only=True)
|
|
||||||
instance_id = serializers.IntegerField(source="instance.id", read_only=True)
|
|
||||||
cue_out = serializers.DurationField(source="get_cueout", read_only=True)
|
|
||||||
ends = serializers.DateTimeField(source="get_ends", read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Schedule
|
|
||||||
fields = [
|
|
||||||
"item_url",
|
|
||||||
"id",
|
|
||||||
"starts",
|
|
||||||
"ends",
|
|
||||||
"file",
|
|
||||||
"file_id",
|
|
||||||
"stream",
|
|
||||||
"stream_id",
|
|
||||||
"clip_length",
|
|
||||||
"fade_in",
|
|
||||||
"fade_out",
|
|
||||||
"cue_in",
|
|
||||||
"cue_out",
|
|
||||||
"media_item_played",
|
|
||||||
"instance",
|
|
||||||
"instance_id",
|
|
||||||
"playout_status",
|
|
||||||
"broadcasted",
|
|
||||||
"position",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class ServiceRegisterSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = ServiceRegister
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class SessionSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Session
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class ShowSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Show
|
|
||||||
fields = [
|
|
||||||
"item_url",
|
|
||||||
"id",
|
|
||||||
"name",
|
|
||||||
"url",
|
|
||||||
"genre",
|
|
||||||
"description",
|
|
||||||
"color",
|
|
||||||
"background_color",
|
|
||||||
"linked",
|
|
||||||
"is_linkable",
|
|
||||||
"image_path",
|
|
||||||
"has_autoplaylist",
|
|
||||||
"autoplaylist_repeat",
|
|
||||||
"autoplaylist",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class ShowDaysSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = ShowDays
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class ShowHostSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = ShowHost
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class ShowInstanceSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
show_id = serializers.IntegerField(source="show.id", read_only=True)
|
|
||||||
file_id = serializers.IntegerField(source="file.id", read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = ShowInstance
|
|
||||||
fields = [
|
|
||||||
"item_url",
|
|
||||||
"id",
|
|
||||||
"description",
|
|
||||||
"starts",
|
|
||||||
"ends",
|
|
||||||
"record",
|
|
||||||
"rebroadcast",
|
|
||||||
"time_filled",
|
|
||||||
"created",
|
|
||||||
"last_scheduled",
|
|
||||||
"modified_instance",
|
|
||||||
"autoplaylist_built",
|
|
||||||
"show",
|
|
||||||
"show_id",
|
|
||||||
"instance",
|
|
||||||
"file",
|
|
||||||
"file_id",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class ShowRebroadcastSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = ShowRebroadcast
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class StreamSettingSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = StreamSetting
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class UserTokenSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = UserToken
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class TimestampSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Timestamp
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class WebstreamSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
id = serializers.IntegerField(read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Webstream
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class WebstreamMetadataSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = WebstreamMetadata
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class CeleryTaskSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = CeleryTask
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class CloudFileSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = CloudFile
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class ImportedPodcastSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = ImportedPodcast
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class PodcastSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Podcast
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class PodcastEpisodeSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = PodcastEpisode
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class StationPodcastSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = StationPodcast
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class ThirdPartyTrackReferenceSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = ThirdPartyTrackReference
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class TrackTypeSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = TrackType
|
|
||||||
fields = "__all__"
|
|
|
@ -1,7 +1,11 @@
|
||||||
# Django settings
|
# Django settings
|
||||||
|
|
||||||
|
For more information on django settings, see https://docs.djangoproject.com/en/3.2/topics/settings/.
|
||||||
|
For the full list of settings and their values, see https://docs.djangoproject.com/en/3.2/ref/settings/.
|
||||||
|
|
||||||
The structure of the django settings module is the following:
|
The structure of the django settings module is the following:
|
||||||
|
|
||||||
- the `__init__.py` (`libretime_api.settings`) module is the django settings entrypoint. The module contains bindings between the user configuration and the django settings. **Advanced users** may edit this file to better integrate the LibreTime API in their setup.
|
|
||||||
- the `_internal.py` module contains application settings for django.
|
- the `_internal.py` module contains application settings for django.
|
||||||
- the `_schema.py` module contains the schema for the user configuration parsing and validation.
|
- the `_schema.py` module contains the schema for the user configuration parsing and validation.
|
||||||
|
- the `prod.py` (`libretime_api.settings.prod`) module is the django settings entrypoint. The module contains bindings between the user configuration and the django settings. **Advanced users** may edit this file to better integrate the LibreTime API in their setup.
|
||||||
|
- the `testing.py` (`libretime_api.settings.testing`) module is the testing django settings entrypoint.
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
# pylint: disable=unused-import
|
|
||||||
from os import getenv
|
|
||||||
|
|
||||||
from ._internal import (
|
|
||||||
AUTH_PASSWORD_VALIDATORS,
|
|
||||||
AUTH_USER_MODEL,
|
|
||||||
DEBUG,
|
|
||||||
INSTALLED_APPS,
|
|
||||||
MIDDLEWARE,
|
|
||||||
REST_FRAMEWORK,
|
|
||||||
ROOT_URLCONF,
|
|
||||||
STATIC_URL,
|
|
||||||
TEMPLATES,
|
|
||||||
TEST_RUNNER,
|
|
||||||
WSGI_APPLICATION,
|
|
||||||
setup_logger,
|
|
||||||
)
|
|
||||||
from ._schema import Config
|
|
||||||
|
|
||||||
API_VERSION = "2.0.0"
|
|
||||||
|
|
||||||
LIBRETIME_LOG_FILEPATH = getenv("LIBRETIME_LOG_FILEPATH")
|
|
||||||
LIBRETIME_CONFIG_FILEPATH = getenv("LIBRETIME_CONFIG_FILEPATH")
|
|
||||||
|
|
||||||
CONFIG = Config(filepath=LIBRETIME_CONFIG_FILEPATH)
|
|
||||||
|
|
||||||
SECRET_KEY = CONFIG.general.api_key
|
|
||||||
ALLOWED_HOSTS = ["*"]
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
"default": {
|
|
||||||
"ENGINE": "django.db.backends.postgresql",
|
|
||||||
"HOST": CONFIG.database.host,
|
|
||||||
"PORT": CONFIG.database.port,
|
|
||||||
"NAME": CONFIG.database.name,
|
|
||||||
"USER": CONFIG.database.user,
|
|
||||||
"PASSWORD": CONFIG.database.password,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LANGUAGE_CODE = "en-us"
|
|
||||||
TIME_ZONE = "UTC"
|
|
||||||
USE_I18N = True
|
|
||||||
USE_L10N = True
|
|
||||||
USE_TZ = True
|
|
||||||
|
|
||||||
LOGGING = setup_logger(LIBRETIME_LOG_FILEPATH)
|
|
||||||
|
|
||||||
SPECTACULAR_SETTINGS = {
|
|
||||||
"TITLE": "LibreTime API",
|
|
||||||
"DESCRIPTION": "Radio Broadcast & Automation Platform",
|
|
||||||
"VERSION": API_VERSION,
|
|
||||||
}
|
|
|
@ -1,13 +1,18 @@
|
||||||
from os import getenv
|
from os import getenv
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
API_VERSION = "2.0.0"
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = getenv("LIBRETIME_DEBUG")
|
DEBUG = getenv("LIBRETIME_DEBUG", "false").lower() == "true"
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
"libretime_api.apps.LibreTimeAPIConfig",
|
"libretime_api.core",
|
||||||
|
"libretime_api.history",
|
||||||
|
"libretime_api.storage",
|
||||||
|
"libretime_api.schedule",
|
||||||
"django.contrib.auth",
|
"django.contrib.auth",
|
||||||
"django.contrib.contenttypes",
|
"django.contrib.contenttypes",
|
||||||
"django.contrib.sessions",
|
"django.contrib.sessions",
|
||||||
|
@ -48,8 +53,19 @@ TEMPLATES = [
|
||||||
|
|
||||||
WSGI_APPLICATION = "libretime_api.wsgi.application"
|
WSGI_APPLICATION = "libretime_api.wsgi.application"
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/3.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = "/api/v2/static/"
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||||
|
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
|
@ -66,39 +82,11 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
# Rest Framework settings
|
|
||||||
# https://www.django-rest-framework.org/api-guide/settings/
|
|
||||||
|
|
||||||
renderer_classes = ["rest_framework.renderers.JSONRenderer"]
|
|
||||||
if DEBUG:
|
|
||||||
renderer_classes += ["rest_framework.renderers.BrowsableAPIRenderer"]
|
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
|
||||||
"DEFAULT_RENDERER_CLASSES": renderer_classes,
|
|
||||||
"DEFAULT_AUTHENTICATION_CLASSES": (
|
|
||||||
"rest_framework.authentication.SessionAuthentication",
|
|
||||||
"rest_framework.authentication.BasicAuthentication",
|
|
||||||
),
|
|
||||||
"DEFAULT_PERMISSION_CLASSES": [
|
|
||||||
"libretime_api.permissions.IsSystemTokenOrUser",
|
|
||||||
],
|
|
||||||
"DEFAULT_FILTER_BACKENDS": [
|
|
||||||
"django_filters.rest_framework.DjangoFilterBackend",
|
|
||||||
],
|
|
||||||
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
|
||||||
"URL_FIELD_NAME": "item_url",
|
|
||||||
}
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
|
||||||
# https://docs.djangoproject.com/en/3.0/howto/static-files/
|
|
||||||
|
|
||||||
STATIC_URL = "/api/v2/static/"
|
|
||||||
|
|
||||||
AUTH_USER_MODEL = "libretime_api.User"
|
|
||||||
|
|
||||||
TEST_RUNNER = "libretime_api.tests.runners.ManagedModelTestRunner"
|
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
|
# https://docs.djangoproject.com/en/3.2/topics/logging/#configuring-logging
|
||||||
|
|
||||||
|
|
||||||
def setup_logger(log_filepath: Optional[str]):
|
def setup_logger(log_filepath: Optional[str]):
|
||||||
logging_handlers = {
|
logging_handlers = {
|
||||||
"console": {
|
"console": {
|
||||||
|
@ -143,3 +131,41 @@ def setup_logger(log_filepath: Optional[str]):
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Rest Framework
|
||||||
|
# https://www.django-rest-framework.org/api-guide/settings/
|
||||||
|
|
||||||
|
renderer_classes = ["rest_framework.renderers.JSONRenderer"]
|
||||||
|
if DEBUG:
|
||||||
|
renderer_classes += ["rest_framework.renderers.BrowsableAPIRenderer"]
|
||||||
|
|
||||||
|
REST_FRAMEWORK = {
|
||||||
|
"DEFAULT_RENDERER_CLASSES": renderer_classes,
|
||||||
|
"DEFAULT_AUTHENTICATION_CLASSES": (
|
||||||
|
"rest_framework.authentication.SessionAuthentication",
|
||||||
|
"rest_framework.authentication.BasicAuthentication",
|
||||||
|
),
|
||||||
|
"DEFAULT_PERMISSION_CLASSES": [
|
||||||
|
"libretime_api.permissions.IsSystemTokenOrUser",
|
||||||
|
],
|
||||||
|
"DEFAULT_FILTER_BACKENDS": [
|
||||||
|
"django_filters.rest_framework.DjangoFilterBackend",
|
||||||
|
],
|
||||||
|
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
||||||
|
"URL_FIELD_NAME": "item_url",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Auth
|
||||||
|
# https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#substituting-a-custom-user-model
|
||||||
|
|
||||||
|
AUTH_USER_MODEL = "core.User"
|
||||||
|
|
||||||
|
# Spectacular
|
||||||
|
# https://drf-spectacular.readthedocs.io/en/latest/settings.html
|
||||||
|
|
||||||
|
SPECTACULAR_SETTINGS = {
|
||||||
|
"TITLE": "LibreTime API",
|
||||||
|
"DESCRIPTION": "Radio Broadcast & Automation Platform",
|
||||||
|
"VERSION": API_VERSION,
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
from os import getenv
|
||||||
|
|
||||||
|
# pylint: disable=unused-import
|
||||||
|
from ._internal import (
|
||||||
|
API_VERSION,
|
||||||
|
AUTH_PASSWORD_VALIDATORS,
|
||||||
|
AUTH_USER_MODEL,
|
||||||
|
DEBUG,
|
||||||
|
DEFAULT_AUTO_FIELD,
|
||||||
|
INSTALLED_APPS,
|
||||||
|
MIDDLEWARE,
|
||||||
|
REST_FRAMEWORK,
|
||||||
|
ROOT_URLCONF,
|
||||||
|
SPECTACULAR_SETTINGS,
|
||||||
|
STATIC_URL,
|
||||||
|
TEMPLATES,
|
||||||
|
WSGI_APPLICATION,
|
||||||
|
setup_logger,
|
||||||
|
)
|
||||||
|
from ._schema import Config
|
||||||
|
|
||||||
|
LIBRETIME_LOG_FILEPATH = getenv("LIBRETIME_LOG_FILEPATH")
|
||||||
|
LIBRETIME_CONFIG_FILEPATH = getenv("LIBRETIME_CONFIG_FILEPATH")
|
||||||
|
|
||||||
|
CONFIG = Config(filepath=LIBRETIME_CONFIG_FILEPATH)
|
||||||
|
|
||||||
|
SECRET_KEY = CONFIG.general.api_key
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ["*"]
|
||||||
|
|
||||||
|
LOGGING = setup_logger(LIBRETIME_LOG_FILEPATH)
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
"default": {
|
||||||
|
"ENGINE": "django.db.backends.postgresql",
|
||||||
|
"HOST": CONFIG.database.host,
|
||||||
|
"PORT": CONFIG.database.port,
|
||||||
|
"NAME": CONFIG.database.name,
|
||||||
|
"USER": CONFIG.database.user,
|
||||||
|
"PASSWORD": CONFIG.database.password,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/3.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = "en-us"
|
||||||
|
TIME_ZONE = "UTC"
|
||||||
|
USE_I18N = True
|
||||||
|
USE_L10N = True
|
||||||
|
USE_TZ = True
|
|
@ -0,0 +1,35 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
os.environ.setdefault("LIBRETIME_DEBUG", "true")
|
||||||
|
os.environ.setdefault("LIBRETIME_GENERAL_API_KEY", "testing")
|
||||||
|
|
||||||
|
# pylint: disable=wrong-import-position,unused-import
|
||||||
|
from .prod import (
|
||||||
|
ALLOWED_HOSTS,
|
||||||
|
API_VERSION,
|
||||||
|
AUTH_PASSWORD_VALIDATORS,
|
||||||
|
AUTH_USER_MODEL,
|
||||||
|
CONFIG,
|
||||||
|
DATABASES,
|
||||||
|
DEBUG,
|
||||||
|
DEFAULT_AUTO_FIELD,
|
||||||
|
INSTALLED_APPS,
|
||||||
|
LANGUAGE_CODE,
|
||||||
|
LOGGING,
|
||||||
|
MIDDLEWARE,
|
||||||
|
REST_FRAMEWORK,
|
||||||
|
ROOT_URLCONF,
|
||||||
|
SECRET_KEY,
|
||||||
|
STATIC_URL,
|
||||||
|
TEMPLATES,
|
||||||
|
TIME_ZONE,
|
||||||
|
USE_I18N,
|
||||||
|
USE_L10N,
|
||||||
|
USE_TZ,
|
||||||
|
WSGI_APPLICATION,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
# https://docs.djangoproject.com/en/3.2/ref/settings/#test-runner
|
||||||
|
|
||||||
|
TEST_RUNNER = "libretime_api.tests.runner.ManagedModelTestRunner"
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class StorageConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "libretime_api.storage"
|
||||||
|
verbose_name = "LibreTime Storage API"
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .cloud_file import CloudFile
|
||||||
|
from .file import File
|
||||||
|
from .storage import MusicDir
|
||||||
|
from .track_type import TrackType
|
|
@ -0,0 +1,13 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class CloudFile(models.Model):
|
||||||
|
storage_backend = models.CharField(max_length=512)
|
||||||
|
resource_id = models.TextField()
|
||||||
|
filename = models.ForeignKey(
|
||||||
|
"File", models.DO_NOTHING, blank=True, null=True, db_column="cc_file_id"
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "cloud_file"
|
|
@ -12,7 +12,7 @@ class File(models.Model):
|
||||||
import_status = models.IntegerField()
|
import_status = models.IntegerField()
|
||||||
currently_accessing = models.IntegerField(db_column="currentlyaccessing")
|
currently_accessing = models.IntegerField(db_column="currentlyaccessing")
|
||||||
edited_by = models.ForeignKey(
|
edited_by = models.ForeignKey(
|
||||||
"User",
|
"core.User",
|
||||||
models.DO_NOTHING,
|
models.DO_NOTHING,
|
||||||
db_column="editedby",
|
db_column="editedby",
|
||||||
blank=True,
|
blank=True,
|
||||||
|
@ -70,7 +70,7 @@ class File(models.Model):
|
||||||
replay_gain = models.DecimalField(
|
replay_gain = models.DecimalField(
|
||||||
max_digits=8, decimal_places=2, blank=True, null=True
|
max_digits=8, decimal_places=2, blank=True, null=True
|
||||||
)
|
)
|
||||||
owner = models.ForeignKey("User", models.DO_NOTHING, blank=True, null=True)
|
owner = models.ForeignKey("core.User", models.DO_NOTHING, blank=True, null=True)
|
||||||
cuein = models.DurationField(blank=True, null=True)
|
cuein = models.DurationField(blank=True, null=True)
|
||||||
cueout = models.DurationField(blank=True, null=True)
|
cueout = models.DurationField(blank=True, null=True)
|
||||||
silan_check = models.BooleanField(blank=True, null=True)
|
silan_check = models.BooleanField(blank=True, null=True)
|
||||||
|
@ -92,26 +92,3 @@ class File(models.Model):
|
||||||
("change_own_file", "Change the files where they are the owner"),
|
("change_own_file", "Change the files where they are the owner"),
|
||||||
("delete_own_file", "Delete the files where they are the owner"),
|
("delete_own_file", "Delete the files where they are the owner"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class MusicDir(models.Model):
|
|
||||||
directory = models.TextField(unique=True, blank=True, null=True)
|
|
||||||
type = models.CharField(max_length=255, blank=True, null=True)
|
|
||||||
exists = models.BooleanField(blank=True, null=True)
|
|
||||||
watched = models.BooleanField(blank=True, null=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "cc_music_dirs"
|
|
||||||
|
|
||||||
|
|
||||||
class CloudFile(models.Model):
|
|
||||||
storage_backend = models.CharField(max_length=512)
|
|
||||||
resource_id = models.TextField()
|
|
||||||
filename = models.ForeignKey(
|
|
||||||
File, models.DO_NOTHING, blank=True, null=True, db_column="cc_file_id"
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = "cloud_file"
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class MusicDir(models.Model):
|
||||||
|
directory = models.TextField(unique=True, blank=True, null=True)
|
||||||
|
type = models.CharField(max_length=255, blank=True, null=True)
|
||||||
|
exists = models.BooleanField(blank=True, null=True)
|
||||||
|
watched = models.BooleanField(blank=True, null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "cc_music_dirs"
|
|
@ -0,0 +1,12 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class TrackType(models.Model):
|
||||||
|
code = models.CharField(max_length=16, unique=True)
|
||||||
|
type_name = models.CharField(max_length=255, blank=True, null=True)
|
||||||
|
description = models.CharField(max_length=255, blank=True, null=True)
|
||||||
|
visibility = models.BooleanField(blank=True, default=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = "cc_track_types"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue