from marietje.utils import send_to_bertha from queues.models import PlaylistSong from songs.models import Song from django.db.models.functions import Coalesce from django.db.models import Sum, Value from django.db import transaction from mutagen import File class UploadException(Exception): pass def is_regular_queue(ps): if not ps.played_at: # Request is from the old times, assume good return True if not 0 <= ps.played_at.astimezone().weekday() <= 4: return False # Queued in the weekend if not 7 <= ps.played_at.astimezone().hour <= 22: # Because of timezone shit, I allow for an extra hour of leeway return False # Queued outside of regular opening hours return True @transaction.atomic def request_weight(ps): if is_regular_queue(ps): return float(ps.song.duration) # Count other requests for 10% return 0.10 * float(ps.song.duration) def get_upload_stats(user): songs_queued = PlaylistSong.objects.select_related("song").filter(user=user, state=2, song__deleted=False) queued_score = sum(request_weight(x) for x in songs_queued) upload_score = Song.objects.filter(user=user, deleted=False).aggregate(x=Coalesce(Sum("duration"), Value(0)))["x"] return {"queued_score": queued_score, "upload_score": upload_score} def get_reputation(user) -> float: try: stats = get_upload_stats(user) ratio = stats["queued_score"] / (2.0 * stats["upload_score"]) return ratio except ZeroDivisionError: return 99999.0 # high enough def check_upload_stats(user): # Allow upload if the user has a good reputation # Score function: # - U = duration * songs uploaded # - Q = duration * songs queued # - If 2*U < Q: allow upload (otherwise don't) if user.is_superuser: return True ratio = get_reputation(user) return ratio >= 1.0 def upload_file(file, artist, title, user): duration = File(file).info.length bertha_hash = send_to_bertha(file).decode("ascii") if not bertha_hash: raise UploadException("Files not uploaded correctly.") return Song.objects.create(user=user, artist=artist, title=title, hash=bertha_hash, duration=duration)