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:
Iulian 2025-12-16 23:43:07 +00:00
commit 51679d1943
254 changed files with 37281 additions and 0 deletions

View file

5
backend/stats/admin.py Normal file
View file

@ -0,0 +1,5 @@
"""Stats admin"""
from django.contrib import admin
# No models to register for stats

View file

5
backend/stats/models.py Normal file
View file

@ -0,0 +1,5 @@
"""Stats models"""
from django.db import models
# Stats are calculated from aggregations, no models needed

View file

@ -0,0 +1,24 @@
"""Stats serializers"""
from rest_framework import serializers
class AudioStatsSerializer(serializers.Serializer):
"""Audio statistics"""
total_count = serializers.IntegerField()
total_duration = serializers.IntegerField(help_text="Total duration in seconds")
total_size = serializers.IntegerField(help_text="Total size in bytes")
total_plays = serializers.IntegerField()
class ChannelStatsSerializer(serializers.Serializer):
"""Channel statistics"""
total_channels = serializers.IntegerField()
subscribed_channels = serializers.IntegerField()
class DownloadStatsSerializer(serializers.Serializer):
"""Download statistics"""
pending = serializers.IntegerField()
completed = serializers.IntegerField()
failed = serializers.IntegerField()

10
backend/stats/urls.py Normal file
View file

@ -0,0 +1,10 @@
"""Stats URL patterns"""
from django.urls import path
from stats.views import AudioStatsView, ChannelStatsView, DownloadStatsView
urlpatterns = [
path('audio/', AudioStatsView.as_view(), name='audio-stats'),
path('channel/', ChannelStatsView.as_view(), name='channel-stats'),
path('download/', DownloadStatsView.as_view(), name='download-stats'),
]

61
backend/stats/views.py Normal file
View file

@ -0,0 +1,61 @@
"""Stats API views"""
from django.db.models import Sum, Count
from rest_framework.response import Response
from audio.models import Audio
from channel.models import Channel
from download.models import DownloadQueue
from stats.serializers import (
AudioStatsSerializer,
ChannelStatsSerializer,
DownloadStatsSerializer,
)
from common.views import ApiBaseView
class AudioStatsView(ApiBaseView):
"""Audio statistics endpoint"""
def get(self, request):
"""Get audio statistics"""
stats = Audio.objects.aggregate(
total_count=Count('id'),
total_duration=Sum('duration'),
total_size=Sum('file_size'),
total_plays=Sum('play_count'),
)
# Handle None values
stats = {k: v or 0 for k, v in stats.items()}
serializer = AudioStatsSerializer(stats)
return Response(serializer.data)
class ChannelStatsView(ApiBaseView):
"""Channel statistics endpoint"""
def get(self, request):
"""Get channel statistics"""
stats = {
'total_channels': Channel.objects.count(),
'subscribed_channels': Channel.objects.filter(subscribed=True).count(),
}
serializer = ChannelStatsSerializer(stats)
return Response(serializer.data)
class DownloadStatsView(ApiBaseView):
"""Download statistics endpoint"""
def get(self, request):
"""Get download statistics"""
stats = {
'pending': DownloadQueue.objects.filter(status='pending').count(),
'completed': DownloadQueue.objects.filter(status='completed').count(),
'failed': DownloadQueue.objects.filter(status='failed').count(),
}
serializer = DownloadStatsSerializer(stats)
return Response(serializer.data)