from datetime import datetime, timedelta from django.core.cache import caches from django.conf import settings from django.db.models import Count, Q, Sum from django.shortcuts import render from django.utils import timezone from queues.models import PlaylistSong from songs.models import Song def recache_stats(): new_stats = compute_stats() caches['default'].delete('stats') caches['default'].set('stats', new_stats, 7200) return new_stats def to_days(time): for tr in time: tr['duration'] = str(round(tr['total']/86400, 2)) + ' days' return time def compute_stats(): # We want to grab the time now, because otherwise we would be reporting a minute too late last_updated = datetime.now() total_uploads = Song.objects.filter(deleted=False).exclude( user_id=None).count() upload_stats = Song.objects.filter(deleted=False).exclude( user_id=None).values( 'user__id', 'user__name').annotate(total=Count('id')).order_by( '-total', 'user__name')[:settings.STATS_TOP_COUNT] total_requests = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).count() request_stats = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'user__id', 'user__name').annotate(total=Count('id')).order_by( '-total', 'user__name')[:settings.STATS_TOP_COUNT] unique_request_stats = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'user__id', 'user__name').annotate( total=Count('song_id', distinct=True), ratio=Count('song_id', distinct=True) / Count('id') * 100).order_by('-total')[:settings.STATS_TOP_COUNT] total_unique_requests = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).distinct().count() most_played_songs = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'song__artist', 'song__title').annotate(total=Count('id')).order_by( '-total', 'song__artist')[:settings.STATS_TOP_COUNT] most_played_songs_14_days = PlaylistSong.objects.filter( state=2, played_at__gte=timezone.now() - timedelta(days=14)).exclude(user_id=None).values( 'song__artist', 'song__title').annotate(total=Count('id')).order_by( '-total', 'song__artist')[:settings.STATS_TOP_COUNT] time_requested = PlaylistSong.objects.filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values( 'user__id', 'user__name').annotate(total=Sum('song__duration')).order_by( '-total')[:settings.STATS_TOP_COUNT] total_time_requested = PlaylistSong.objects.all().filter(state=2).exclude( Q(user_id=None) | Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).aggregate( total=Sum('song__duration')) return { 'last_updated': last_updated, 'total_uploads': total_uploads, 'upload_stats': list(upload_stats), 'total_requests': total_requests, 'request_stats': list(request_stats), 'unique_request_stats': list(unique_request_stats), 'total_unique_requests': total_unique_requests, 'most_played_songs': list(most_played_songs), 'most_played_songs_14_days': list(most_played_songs_14_days), 'time_requested': to_days(list(time_requested)), 'total_time_requested': str(round(float(total_time_requested['total'])/86400, 2)) + ' days', 'stats_top_count': settings.STATS_TOP_COUNT, }