Files
MarietjeDjango/marietje/stats/utils.py
2019-01-23 19:44:38 +01:00

169 lines
7.0 KiB
Python

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.utils import timezone
from queues.models import PlaylistSong
from songs.models import Song
from marietje.models import User
def recache_stats():
new_stats = compute_stats()
caches['default'].delete('stats')
caches['default'].set('stats', new_stats, 2 * 3600)
return new_stats
def recache_user_stats():
users = User.objects.exclude(Q(id=None)
| Q(id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values('id')
for user in users:
new_stats = user_stats(user['id'])
cacheloc = 'userstats_{}'.format(user['id'])
caches['default'].delete(cacheloc)
caches['default'].set(cacheloc, new_stats, 48 * 3600)
return new_stats
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_requests=Count('id', distinct=True),
unique_requests=Count('song__id', distinct=True)).order_by(
'-total_requests')[: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)).aggregate(
total=Count('song__id', distinct=True))
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'))
most_requested_uploaders = PlaylistSong.objects.filter(state=2).exclude(
Q(user_id=None)
| Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values(
'song__user__id', 'song__user__name').annotate(total=Count(
'song__user__id')).order_by('-total')[:settings.STATS_TOP_COUNT]
# Convert requested time to days
time_requested = list(time_requested)
for tr in time_requested:
tr['duration'] = str(round(tr['total'] / 86400, 2)) + ' days'
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': time_requested,
'total_time_requested': str(round(float(total_time_requested['total']) / 86400, 2)) + ' days',
'stats_top_count': settings.STATS_TOP_COUNT,
'most_requested_uploaders': list(most_requested_uploaders),
}
def user_stats(request):
last_updated = datetime.now()
total_uploads = Song.objects.filter(
user__id=request, deleted=False).count()
total_requests = PlaylistSong.objects.filter(
user__id=request, state=2).count()
unique_requests = PlaylistSong.objects.filter(
user__id=request, state=2,
song_id__isnull=False).values('song_id').distinct().count()
most_played_songs = PlaylistSong.objects.filter(
user__id=request, 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',
'song__title')[:settings.STATS_TOP_COUNT]
most_played_uploaders = PlaylistSong.objects.filter(
user__id=request, state=2).exclude(
Q(user_id=None)
| Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values(
'song__user__id', 'song__user__name').annotate(
total=Count('song__user__id')).order_by(
'-total')[:settings.STATS_TOP_COUNT]
most_played_uploads = PlaylistSong.objects.filter(
state=2, song_id__in=Song.objects.filter(user__id=request)).exclude(
Q(user_id=None)
| Q(user_id__in=settings.STATS_REQUEST_IGNORE_USER_IDS)).values(
'pk').values(
'song__artist',
'song__title').annotate(total=Count('id')).order_by(
'-total', 'song__artist',
'song__title')[:settings.STATS_TOP_COUNT]
total_played_uploads = most_played_uploads.aggregate(newtotal=Sum('total'))
return {
'last_updated': last_updated,
'total_uploads': total_uploads,
'total_requests': total_requests,
'unique_requests': unique_requests,
'most_played_songs': list(most_played_songs),
'most_played_uploaders': list(most_played_uploaders),
'most_played_uploads': list(most_played_uploads),
'stats_top_count': settings.STATS_TOP_COUNT,
'total_played_uploads': total_played_uploads['newtotal'],
}