Initial commit - SoundWave v1.0
- Full PWA support with offline capabilities - Comprehensive search across songs, playlists, and channels - Offline playlist manager with download tracking - Pre-built frontend for zero-build deployment - Docker-based deployment with docker compose - Material-UI dark theme interface - YouTube audio download and management - Multi-user authentication support
This commit is contained in:
commit
51679d1943
254 changed files with 37281 additions and 0 deletions
0
backend/download/__init__.py
Normal file
0
backend/download/__init__.py
Normal file
12
backend/download/admin.py
Normal file
12
backend/download/admin.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
"""Download admin"""
|
||||
|
||||
from django.contrib import admin
|
||||
from download.models import DownloadQueue
|
||||
|
||||
|
||||
@admin.register(DownloadQueue)
|
||||
class DownloadQueueAdmin(admin.ModelAdmin):
|
||||
"""Download queue admin"""
|
||||
list_display = ('title', 'channel_name', 'status', 'added_date', 'auto_start')
|
||||
list_filter = ('status', 'auto_start', 'added_date')
|
||||
search_fields = ('title', 'url', 'youtube_id')
|
||||
0
backend/download/migrations/__init__.py
Normal file
0
backend/download/migrations/__init__.py
Normal file
40
backend/download/models.py
Normal file
40
backend/download/models.py
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
"""Download queue models"""
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class DownloadQueue(models.Model):
|
||||
"""Download queue model"""
|
||||
STATUS_CHOICES = [
|
||||
('pending', 'Pending'),
|
||||
('downloading', 'Downloading'),
|
||||
('completed', 'Completed'),
|
||||
('failed', 'Failed'),
|
||||
('ignored', 'Ignored'),
|
||||
]
|
||||
|
||||
owner = models.ForeignKey(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='download_queue',
|
||||
help_text="User who owns this download"
|
||||
)
|
||||
url = models.URLField(max_length=500)
|
||||
youtube_id = models.CharField(max_length=50, blank=True)
|
||||
title = models.CharField(max_length=500, blank=True)
|
||||
channel_name = models.CharField(max_length=200, blank=True)
|
||||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
|
||||
error_message = models.TextField(blank=True)
|
||||
added_date = models.DateTimeField(auto_now_add=True)
|
||||
started_date = models.DateTimeField(null=True, blank=True)
|
||||
completed_date = models.DateTimeField(null=True, blank=True)
|
||||
auto_start = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-auto_start', 'added_date']
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.title or self.url} - {self.status}"
|
||||
22
backend/download/serializers.py
Normal file
22
backend/download/serializers.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
"""Download serializers"""
|
||||
|
||||
from rest_framework import serializers
|
||||
from download.models import DownloadQueue
|
||||
|
||||
|
||||
class DownloadQueueSerializer(serializers.ModelSerializer):
|
||||
"""Download queue serializer"""
|
||||
|
||||
class Meta:
|
||||
model = DownloadQueue
|
||||
fields = '__all__'
|
||||
read_only_fields = ['added_date', 'started_date', 'completed_date']
|
||||
|
||||
|
||||
class AddToDownloadSerializer(serializers.Serializer):
|
||||
"""Add to download queue"""
|
||||
urls = serializers.ListField(
|
||||
child=serializers.URLField(),
|
||||
allow_empty=False
|
||||
)
|
||||
auto_start = serializers.BooleanField(default=False)
|
||||
8
backend/download/urls.py
Normal file
8
backend/download/urls.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
"""Download URL patterns"""
|
||||
|
||||
from django.urls import path
|
||||
from download.views import DownloadListView
|
||||
|
||||
urlpatterns = [
|
||||
path('', DownloadListView.as_view(), name='download-list'),
|
||||
]
|
||||
42
backend/download/views.py
Normal file
42
backend/download/views.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
"""Download API views"""
|
||||
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
from download.models import DownloadQueue
|
||||
from download.serializers import DownloadQueueSerializer, AddToDownloadSerializer
|
||||
from common.views import ApiBaseView, AdminWriteOnly
|
||||
|
||||
|
||||
class DownloadListView(ApiBaseView):
|
||||
"""Download queue list endpoint"""
|
||||
permission_classes = [AdminWriteOnly]
|
||||
|
||||
def get(self, request):
|
||||
"""Get download queue"""
|
||||
status_filter = request.query_params.get('filter', 'pending')
|
||||
queryset = DownloadQueue.objects.filter(owner=request.user, status=status_filter)
|
||||
serializer = DownloadQueueSerializer(queryset, many=True)
|
||||
return Response({'data': serializer.data})
|
||||
|
||||
def post(self, request):
|
||||
"""Add to download queue"""
|
||||
serializer = AddToDownloadSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
created_items = []
|
||||
for url in serializer.validated_data['urls']:
|
||||
item, created = DownloadQueue.objects.get_or_create(
|
||||
owner=request.user,
|
||||
url=url,
|
||||
defaults={'auto_start': serializer.validated_data['auto_start']}
|
||||
)
|
||||
created_items.append(item)
|
||||
|
||||
response_serializer = DownloadQueueSerializer(created_items, many=True)
|
||||
return Response(response_serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
def delete(self, request):
|
||||
"""Clear download queue"""
|
||||
status_filter = request.query_params.get('filter', 'pending')
|
||||
DownloadQueue.objects.filter(owner=request.user, status=status_filter).delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
Loading…
Add table
Add a link
Reference in a new issue