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:
|
||||
shell: bash
|
||||
env:
|
||||
LIBRETIME_GENERAL_API_KEY: test_key
|
||||
LIBRETIME_DATABASE_HOST: postgres
|
||||
|
||||
steps:
|
||||
|
|
|
@ -13,4 +13,4 @@ clean: .clean
|
|||
|
||||
test: $(VENV)
|
||||
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"),)
|
||||
|
||||
|
||||
class MountName(models.Model):
|
||||
mount_name = models.CharField(max_length=1024)
|
||||
|
||||
class Meta:
|
||||
managed = False
|
||||
db_table = "cc_mount_name"
|
||||
|
||||
|
||||
class StreamSetting(models.Model):
|
||||
keyname = models.CharField(primary_key=True, max_length=64)
|
||||
value = models.CharField(max_length=255, blank=True, null=True)
|
|
@ -1,43 +1,37 @@
|
|||
import hashlib
|
||||
|
||||
from django.contrib import auth
|
||||
from django.contrib.auth.models import AbstractBaseUser, Permission
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, Permission
|
||||
from django.db import models
|
||||
|
||||
from libretime_api.managers import UserManager
|
||||
from libretime_api.permission_constants import GROUPS
|
||||
|
||||
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"
|
||||
|
||||
from ...permission_constants import GROUPS
|
||||
from .role import ADMIN, USER_TYPES
|
||||
|
||||
USER_TYPE_CHOICES = ()
|
||||
for item in USER_TYPES.items():
|
||||
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):
|
||||
username = models.CharField(db_column="login", unique=True, max_length=255)
|
||||
password = models.CharField(
|
||||
|
@ -132,17 +126,3 @@ class User(AbstractBaseUser):
|
|||
class Meta:
|
||||
managed = False
|
||||
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
|
||||
|
||||
|
||||
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):
|
||||
task_id = models.CharField(max_length=256)
|
||||
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.contrib.auth.models import Group
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from libretime_api.models import User
|
||||
from libretime_api.models.user_constants import DJ, GUEST
|
||||
from libretime_api.permission_constants import GROUPS
|
||||
from ....permission_constants import GROUPS
|
||||
from ...models import DJ, GUEST, User
|
||||
|
||||
|
||||
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 .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):
|
||||
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()
|
||||
ends = models.DateTimeField(blank=True, null=True)
|
||||
instance = models.ForeignKey(
|
||||
"ShowInstance", models.DO_NOTHING, blank=True, null=True
|
||||
"schedule.ShowInstance", models.DO_NOTHING, blank=True, null=True
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -37,7 +15,7 @@ class PlayoutHistory(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)
|
||||
value = models.CharField(max_length=128)
|
||||
|
||||
|
@ -56,7 +34,7 @@ class PlayoutHistoryTemplate(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)
|
||||
label = models.CharField(max_length=128)
|
||||
type = models.CharField(max_length=128)
|
||||
|
@ -66,11 +44,3 @@ class PlayoutHistoryTemplateField(models.Model):
|
|||
class Meta:
|
||||
managed = False
|
||||
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."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
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")
|
||||
try:
|
||||
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 django.contrib.auth.models import Group, Permission
|
||||
|
||||
from .models.user_constants import DJ, GUEST, PROGRAM_MANAGER, USER_TYPES
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
from .core.models import DJ, GUEST, PROGRAM_MANAGER, USER_TYPES
|
||||
|
||||
GUEST_PERMISSIONS = [
|
||||
"view_schedule",
|
||||
|
@ -24,6 +18,7 @@ GUEST_PERMISSIONS = [
|
|||
"view_webstream",
|
||||
"view_apiroot",
|
||||
]
|
||||
|
||||
DJ_PERMISSIONS = GUEST_PERMISSIONS + [
|
||||
"add_file",
|
||||
"add_podcast",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf import settings
|
||||
from rest_framework.permissions import BasePermission
|
||||
|
||||
from .models.user_constants import DJ
|
||||
from .core.models.role import DJ
|
||||
|
||||
REQUEST_PERMISSION_TYPE_MAP = {
|
||||
"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 .files import File
|
||||
from .smart_blocks import SmartBlock
|
||||
|
||||
|
||||
class Playlist(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
mtime = 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)
|
||||
length = models.DurationField(blank=True, null=True)
|
||||
|
||||
|
@ -21,9 +18,9 @@ class Playlist(models.Model):
|
|||
|
||||
|
||||
class PlaylistContent(models.Model):
|
||||
playlist = models.ForeignKey(Playlist, models.DO_NOTHING, blank=True, null=True)
|
||||
file = models.ForeignKey(File, models.DO_NOTHING, blank=True, null=True)
|
||||
block = models.ForeignKey(SmartBlock, models.DO_NOTHING, blank=True, null=True)
|
||||
playlist = models.ForeignKey("Playlist", 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)
|
||||
stream_id = models.IntegerField(blank=True, null=True)
|
||||
type = models.SmallIntegerField()
|
||||
position = models.IntegerField(blank=True, null=True)
|
|
@ -1,22 +1,5 @@
|
|||
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):
|
||||
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_explicit = models.CharField(max_length=4096, blank=True, null=True)
|
||||
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):
|
||||
|
@ -49,8 +32,8 @@ class Podcast(models.Model):
|
|||
|
||||
|
||||
class PodcastEpisode(models.Model):
|
||||
file = models.ForeignKey(File, models.DO_NOTHING, blank=True, null=True)
|
||||
podcast = models.ForeignKey(Podcast, models.DO_NOTHING)
|
||||
file = models.ForeignKey("storage.File", models.DO_NOTHING, blank=True, null=True)
|
||||
podcast = models.ForeignKey("Podcast", models.DO_NOTHING)
|
||||
publication_date = models.DateTimeField()
|
||||
download_url = models.CharField(max_length=4096)
|
||||
episode_guid = models.CharField(max_length=4096)
|
||||
|
@ -76,7 +59,7 @@ class PodcastEpisode(models.Model):
|
|||
|
||||
|
||||
class StationPodcast(models.Model):
|
||||
podcast = models.ForeignKey(Podcast, models.DO_NOTHING)
|
||||
podcast = models.ForeignKey("Podcast", models.DO_NOTHING)
|
||||
|
||||
def get_owner(self):
|
||||
return self.podcast.owner
|
||||
|
@ -84,3 +67,17 @@ class StationPodcast(models.Model):
|
|||
class Meta:
|
||||
managed = False
|
||||
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 .files import File
|
||||
|
||||
|
||||
class Schedule(models.Model):
|
||||
starts = 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)
|
||||
clip_length = models.DurationField(blank=True, null=True)
|
||||
fade_in = models.TimeField(blank=True, null=True)
|
|
@ -1,8 +1,5 @@
|
|||
from django.db import models
|
||||
|
||||
from .files import File
|
||||
from .playlists import Playlist
|
||||
|
||||
|
||||
class Show(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
|
@ -19,7 +16,9 @@ class Show(models.Model):
|
|||
is_linkable = models.BooleanField()
|
||||
image_path = models.CharField(max_length=255, blank=True, null=True)
|
||||
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()
|
||||
|
||||
def get_owner(self):
|
||||
|
@ -39,7 +38,7 @@ class ShowDays(models.Model):
|
|||
day = models.SmallIntegerField(blank=True, null=True)
|
||||
repeat_type = models.SmallIntegerField()
|
||||
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)
|
||||
|
||||
def get_owner(self):
|
||||
|
@ -51,8 +50,8 @@ class ShowDays(models.Model):
|
|||
|
||||
|
||||
class ShowHost(models.Model):
|
||||
show = models.ForeignKey(Show, models.DO_NOTHING)
|
||||
subjs = models.ForeignKey("User", models.DO_NOTHING)
|
||||
show = models.ForeignKey("Show", models.DO_NOTHING)
|
||||
subjs = models.ForeignKey("core.User", models.DO_NOTHING)
|
||||
|
||||
class Meta:
|
||||
managed = False
|
||||
|
@ -63,11 +62,11 @@ class ShowInstance(models.Model):
|
|||
description = models.CharField(max_length=8192, blank=True, null=True)
|
||||
starts = 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)
|
||||
rebroadcast = models.SmallIntegerField(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)
|
||||
created = models.DateTimeField()
|
||||
last_scheduled = models.DateTimeField(blank=True, null=True)
|
||||
|
@ -85,7 +84,7 @@ class ShowInstance(models.Model):
|
|||
class ShowRebroadcast(models.Model):
|
||||
day_offset = models.CharField(max_length=1024)
|
||||
start_time = models.TimeField()
|
||||
show = models.ForeignKey(Show, models.DO_NOTHING)
|
||||
show = models.ForeignKey("Show", models.DO_NOTHING)
|
||||
|
||||
def get_owner(self):
|
||||
return show.get_owner()
|
|
@ -5,7 +5,7 @@ class SmartBlock(models.Model):
|
|||
name = models.CharField(max_length=255)
|
||||
mtime = 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)
|
||||
length = models.DurationField(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):
|
||||
block = models.ForeignKey(SmartBlock, models.DO_NOTHING, blank=True, null=True)
|
||||
file = models.ForeignKey("File", models.DO_NOTHING, blank=True, null=True)
|
||||
block = models.ForeignKey("SmartBlock", 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)
|
||||
trackoffset = models.FloatField()
|
||||
cliplength = models.DurationField(blank=True, null=True)
|
||||
|
@ -63,7 +63,7 @@ class SmartBlockCriteria(models.Model):
|
|||
value = models.CharField(max_length=512)
|
||||
extra = models.CharField(max_length=512, 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):
|
||||
return self.block.get_owner()
|
|
@ -1,8 +1,6 @@
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.db import models
|
||||
|
||||
from .schedule import Schedule
|
||||
|
||||
|
||||
class Webstream(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
|
@ -29,7 +27,7 @@ class Webstream(models.Model):
|
|||
|
||||
|
||||
class WebstreamMetadata(models.Model):
|
||||
instance = models.ForeignKey(Schedule, models.DO_NOTHING)
|
||||
instance = models.ForeignKey("Schedule", models.DO_NOTHING)
|
||||
start_time = models.DateTimeField()
|
||||
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 libretime_api.models import Schedule, ShowInstance
|
||||
from ...models import Schedule, ShowInstance
|
||||
|
||||
|
||||
class TestSchedule(TestCase):
|
|
@ -2,47 +2,11 @@ import os
|
|||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.utils import dateparse
|
||||
from model_bakery import baker
|
||||
from rest_framework.test import APIRequestFactory, APITestCase
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from libretime_api.views import FileViewSet
|
||||
|
||||
|
||||
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)
|
||||
from ...._fixtures import AUDIO_FILENAME, fixture_path
|
||||
|
||||
|
||||
class TestScheduleViewSet(APITestCase):
|
||||
|
@ -53,25 +17,25 @@ class TestScheduleViewSet(APITestCase):
|
|||
|
||||
def test_schedule_item_full_length(self):
|
||||
music_dir = baker.make(
|
||||
"libretime_api.MusicDir",
|
||||
directory=os.path.join(os.path.dirname(__file__), "resources"),
|
||||
"storage.MusicDir",
|
||||
directory=str(fixture_path),
|
||||
)
|
||||
f = baker.make(
|
||||
"libretime_api.File",
|
||||
"storage.File",
|
||||
directory=music_dir,
|
||||
mime="audio/mp3",
|
||||
filepath="song.mp3",
|
||||
filepath=AUDIO_FILENAME,
|
||||
length=timedelta(seconds=40.86),
|
||||
cuein=timedelta(seconds=0),
|
||||
cueout=timedelta(seconds=40.8131),
|
||||
)
|
||||
show = baker.make(
|
||||
"libretime_api.ShowInstance",
|
||||
"schedule.ShowInstance",
|
||||
starts=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
||||
ends=datetime.now(tz=timezone.utc) + timedelta(minutes=5),
|
||||
)
|
||||
scheduleItem = baker.make(
|
||||
"libretime_api.Schedule",
|
||||
"schedule.Schedule",
|
||||
starts=datetime.now(tz=timezone.utc),
|
||||
ends=datetime.now(tz=timezone.utc) + f.length,
|
||||
cue_out=f.cueout,
|
||||
|
@ -87,25 +51,25 @@ class TestScheduleViewSet(APITestCase):
|
|||
|
||||
def test_schedule_item_trunc(self):
|
||||
music_dir = baker.make(
|
||||
"libretime_api.MusicDir",
|
||||
directory=os.path.join(os.path.dirname(__file__), "resources"),
|
||||
"storage.MusicDir",
|
||||
directory=str(fixture_path),
|
||||
)
|
||||
f = baker.make(
|
||||
"libretime_api.File",
|
||||
"storage.File",
|
||||
directory=music_dir,
|
||||
mime="audio/mp3",
|
||||
filepath="song.mp3",
|
||||
filepath=AUDIO_FILENAME,
|
||||
length=timedelta(seconds=40.86),
|
||||
cuein=timedelta(seconds=0),
|
||||
cueout=timedelta(seconds=40.8131),
|
||||
)
|
||||
show = baker.make(
|
||||
"libretime_api.ShowInstance",
|
||||
"schedule.ShowInstance",
|
||||
starts=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
||||
ends=datetime.now(tz=timezone.utc) + timedelta(seconds=20),
|
||||
)
|
||||
scheduleItem = baker.make(
|
||||
"libretime_api.Schedule",
|
||||
"schedule.Schedule",
|
||||
starts=datetime.now(tz=timezone.utc),
|
||||
ends=datetime.now(tz=timezone.utc) + f.length,
|
||||
instance=show,
|
||||
|
@ -124,33 +88,33 @@ class TestScheduleViewSet(APITestCase):
|
|||
|
||||
def test_schedule_item_invalid(self):
|
||||
music_dir = baker.make(
|
||||
"libretime_api.MusicDir",
|
||||
directory=os.path.join(os.path.dirname(__file__), "resources"),
|
||||
"storage.MusicDir",
|
||||
directory=str(fixture_path),
|
||||
)
|
||||
f = baker.make(
|
||||
"libretime_api.File",
|
||||
"storage.File",
|
||||
directory=music_dir,
|
||||
mime="audio/mp3",
|
||||
filepath="song.mp3",
|
||||
filepath=AUDIO_FILENAME,
|
||||
length=timedelta(seconds=40.86),
|
||||
cuein=timedelta(seconds=0),
|
||||
cueout=timedelta(seconds=40.8131),
|
||||
)
|
||||
show = baker.make(
|
||||
"libretime_api.ShowInstance",
|
||||
"schedule.ShowInstance",
|
||||
starts=datetime.now(tz=timezone.utc) - timedelta(minutes=5),
|
||||
ends=datetime.now(tz=timezone.utc) + timedelta(minutes=5),
|
||||
)
|
||||
scheduleItem = baker.make(
|
||||
"libretime_api.Schedule",
|
||||
schedule_item = baker.make(
|
||||
"schedule.Schedule",
|
||||
starts=datetime.now(tz=timezone.utc),
|
||||
ends=datetime.now(tz=timezone.utc) + f.length,
|
||||
cue_out=f.cueout,
|
||||
instance=show,
|
||||
file=f,
|
||||
)
|
||||
invalidScheduleItem = baker.make(
|
||||
"libretime_api.Schedule",
|
||||
invalid_schedule_item = baker.make(
|
||||
"schedule.Schedule",
|
||||
starts=show.ends + timedelta(minutes=1),
|
||||
ends=show.ends + timedelta(minutes=1) + f.length,
|
||||
cue_out=f.cueout,
|
||||
|
@ -163,19 +127,21 @@ class TestScheduleViewSet(APITestCase):
|
|||
result = response.json()
|
||||
# The invalid item should be filtered out and not returned
|
||||
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)
|
||||
|
||||
def test_schedule_item_range(self):
|
||||
music_dir = baker.make(
|
||||
"libretime_api.MusicDir",
|
||||
directory=os.path.join(os.path.dirname(__file__), "resources"),
|
||||
"storage.MusicDir",
|
||||
directory=str(fixture_path),
|
||||
)
|
||||
f = baker.make(
|
||||
"libretime_api.File",
|
||||
"storage.File",
|
||||
directory=music_dir,
|
||||
mime="audio/mp3",
|
||||
filepath="song.mp3",
|
||||
filepath=AUDIO_FILENAME,
|
||||
length=timedelta(seconds=40.86),
|
||||
cuein=timedelta(seconds=0),
|
||||
cueout=timedelta(seconds=40.8131),
|
||||
|
@ -183,12 +149,12 @@ class TestScheduleViewSet(APITestCase):
|
|||
filter_point = datetime.now(tz=timezone.utc)
|
||||
|
||||
show = baker.make(
|
||||
"libretime_api.ShowInstance",
|
||||
"schedule.ShowInstance",
|
||||
starts=filter_point - timedelta(minutes=5),
|
||||
ends=filter_point + timedelta(minutes=5),
|
||||
)
|
||||
schedule_item = baker.make(
|
||||
"libretime_api.Schedule",
|
||||
"schedule.Schedule",
|
||||
starts=filter_point,
|
||||
ends=filter_point + f.length,
|
||||
cue_out=f.cueout,
|
||||
|
@ -196,7 +162,7 @@ class TestScheduleViewSet(APITestCase):
|
|||
file=f,
|
||||
)
|
||||
previous_item = baker.make(
|
||||
"libretime_api.Schedule",
|
||||
"schedule.Schedule",
|
||||
starts=filter_point - timedelta(minutes=5),
|
||||
ends=filter_point - timedelta(minutes=5) + f.length,
|
||||
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
|
||||
|
||||
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 `__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 `_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 typing import Optional
|
||||
|
||||
API_VERSION = "2.0.0"
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = getenv("LIBRETIME_DEBUG")
|
||||
DEBUG = getenv("LIBRETIME_DEBUG", "false").lower() == "true"
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"libretime_api.apps.LibreTimeAPIConfig",
|
||||
"libretime_api.core",
|
||||
"libretime_api.history",
|
||||
"libretime_api.storage",
|
||||
"libretime_api.schedule",
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
|
@ -48,8 +53,19 @@ TEMPLATES = [
|
|||
|
||||
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
|
||||
# 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 = [
|
||||
{
|
||||
|
@ -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
|
||||
# https://docs.djangoproject.com/en/3.2/topics/logging/#configuring-logging
|
||||
|
||||
|
||||
def setup_logger(log_filepath: Optional[str]):
|
||||
logging_handlers = {
|
||||
"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()
|
||||
currently_accessing = models.IntegerField(db_column="currentlyaccessing")
|
||||
edited_by = models.ForeignKey(
|
||||
"User",
|
||||
"core.User",
|
||||
models.DO_NOTHING,
|
||||
db_column="editedby",
|
||||
blank=True,
|
||||
|
@ -70,7 +70,7 @@ class File(models.Model):
|
|||
replay_gain = models.DecimalField(
|
||||
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)
|
||||
cueout = models.DurationField(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"),
|
||||
("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