Browse Source

Condense live charts to one function

Colin Powell 2 years ago
parent
commit
f76aaf6a9c
2 changed files with 55 additions and 76 deletions
  1. 8 13
      tests/scrobbles_tests/test_aggregators.py
  2. 47 63
      vrobbler/apps/music/aggregators.py

+ 8 - 13
tests/scrobbles_tests/test_aggregators.py

@@ -5,12 +5,7 @@ import time_machine
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
-from music.aggregators import (
-    scrobble_counts,
-    top_artists,
-    top_tracks,
-    week_of_scrobbles,
-)
+from music.aggregators import live_charts, scrobble_counts, week_of_scrobbles
 from profiles.models import UserProfile
 from profiles.models import UserProfile
 from scrobbles.models import Scrobble
 from scrobbles.models import Scrobble
 
 
@@ -55,7 +50,7 @@ def test_week_of_scrobbles_data(client, mopidy_track_request_data):
 def test_top_tracks_by_day(client, mopidy_track_request_data):
 def test_top_tracks_by_day(client, mopidy_track_request_data):
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     user = get_user_model().objects.first()
     user = get_user_model().objects.first()
-    tops = top_tracks(user)
+    tops = live_charts(user)
     assert tops[0].title == "Same in the End"
     assert tops[0].title == "Same in the End"
 
 
 
 
@@ -63,7 +58,7 @@ def test_top_tracks_by_day(client, mopidy_track_request_data):
 def test_top_tracks_by_week(client, mopidy_track_request_data):
 def test_top_tracks_by_week(client, mopidy_track_request_data):
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     user = get_user_model().objects.first()
     user = get_user_model().objects.first()
-    tops = top_tracks(user, filter='week')
+    tops = live_charts(user, chart_period='week')
     assert tops[0].title == "Same in the End"
     assert tops[0].title == "Same in the End"
 
 
 
 
@@ -71,7 +66,7 @@ def test_top_tracks_by_week(client, mopidy_track_request_data):
 def test_top_tracks_by_month(client, mopidy_track_request_data):
 def test_top_tracks_by_month(client, mopidy_track_request_data):
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     user = get_user_model().objects.first()
     user = get_user_model().objects.first()
-    tops = top_tracks(user, filter='month')
+    tops = live_charts(user, chart_period='month')
     assert tops[0].title == "Same in the End"
     assert tops[0].title == "Same in the End"
 
 
 
 
@@ -79,7 +74,7 @@ def test_top_tracks_by_month(client, mopidy_track_request_data):
 def test_top_tracks_by_year(client, mopidy_track_request_data):
 def test_top_tracks_by_year(client, mopidy_track_request_data):
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     user = get_user_model().objects.first()
     user = get_user_model().objects.first()
-    tops = top_tracks(user, filter='year')
+    tops = live_charts(user, chart_period='year')
     assert tops[0].title == "Same in the End"
     assert tops[0].title == "Same in the End"
 
 
 
 
@@ -87,7 +82,7 @@ def test_top_tracks_by_year(client, mopidy_track_request_data):
 def test_top__artists_by_week(client, mopidy_track_request_data):
 def test_top__artists_by_week(client, mopidy_track_request_data):
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     user = get_user_model().objects.first()
     user = get_user_model().objects.first()
-    tops = top_artists(user, filter='week')
+    tops = live_charts(user, chart_period='week', media_type="Artist")
     assert tops[0].name == "Sublime"
     assert tops[0].name == "Sublime"
 
 
 
 
@@ -95,7 +90,7 @@ def test_top__artists_by_week(client, mopidy_track_request_data):
 def test_top__artists_by_month(client, mopidy_track_request_data):
 def test_top__artists_by_month(client, mopidy_track_request_data):
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     user = get_user_model().objects.first()
     user = get_user_model().objects.first()
-    tops = top_artists(user, filter='month')
+    tops = live_charts(user, chart_period='month', media_type="Artist")
     assert tops[0].name == "Sublime"
     assert tops[0].name == "Sublime"
 
 
 
 
@@ -103,5 +98,5 @@ def test_top__artists_by_month(client, mopidy_track_request_data):
 def test_top__artists_by_year(client, mopidy_track_request_data):
 def test_top__artists_by_year(client, mopidy_track_request_data):
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     build_scrobbles(client, mopidy_track_request_data, 7, 1)
     user = get_user_model().objects.first()
     user = get_user_model().objects.first()
-    tops = top_artists(user, filter='year')
+    tops = live_charts(user, chart_period='year', media_type="Artist")
     assert tops[0].name == "Sublime"
     assert tops[0].name == "Sublime"

+ 47 - 63
vrobbler/apps/music/aggregators.py

@@ -1,22 +1,14 @@
 from datetime import datetime, timedelta
 from datetime import datetime, timedelta
-from typing import List, Optional
+from typing import List
 
 
-import pytz
-from django.db.models import Count, Q, Sum
+from django.apps import apps
+from django.db.models import Count, Q, QuerySet
 from django.utils import timezone
 from django.utils import timezone
 from music.models import Artist, Track
 from music.models import Artist, Track
 from scrobbles.models import Scrobble
 from scrobbles.models import Scrobble
 from videos.models import Video
 from videos.models import Video
 from vrobbler.apps.profiles.utils import now_user_timezone
 from vrobbler.apps.profiles.utils import now_user_timezone
 
 
-NOW = timezone.now()
-START_OF_TODAY = datetime.combine(NOW.date(), datetime.min.time(), NOW.tzinfo)
-STARTING_DAY_OF_CURRENT_WEEK = NOW.date() - timedelta(
-    days=NOW.today().isoweekday() % 7
-)
-STARTING_DAY_OF_CURRENT_MONTH = NOW.date().replace(day=1)
-STARTING_DAY_OF_CURRENT_YEAR = NOW.date().replace(month=1, day=1)
-
 
 
 def scrobble_counts(user=None):
 def scrobble_counts(user=None):
 
 
@@ -92,73 +84,65 @@ def week_of_scrobbles(
     return scrobble_day_dict
     return scrobble_day_dict
 
 
 
 
-def top_tracks(
-    user: "User", filter: str = "today", limit: int = 30
-) -> List["Track"]:
-
+def live_charts(
+    user: "User",
+    media_type: str = "Track",
+    chart_period: str = "all",
+    limit: int = 15,
+) -> QuerySet:
     now = timezone.now()
     now = timezone.now()
+    tzinfo = now.tzinfo
+    now = now.date()
     if user.is_authenticated:
     if user.is_authenticated:
         now = now_user_timezone(user.profile)
         now = now_user_timezone(user.profile)
+        tzinfo = now.tzinfo
 
 
-    start_of_today = datetime.combine(
-        now.date(), datetime.min.time(), now.tzinfo
-    )
-    starting_day_of_current_week = now.date() - timedelta(
-        days=now.today().isoweekday() % 7
-    )
-    starting_day_of_current_month = now.date().replace(day=1)
-    starting_day_of_current_year = now.date().replace(month=1, day=1)
+    start_of_today = datetime.combine(now, datetime.min.time(), tzinfo)
+    start_day_of_week = now - timedelta(days=now.today().isoweekday() % 7)
+    start_day_of_month = now.replace(day=1)
+    start_day_of_year = now.replace(month=1, day=1)
 
 
-    time_filter = Q()
-    if filter == "today":
-        time_filter = Q(scrobble__timestamp__gte=start_of_today)
-    if filter == "week":
-        time_filter = Q(scrobble__timestamp__gte=starting_day_of_current_week)
-    if filter == "month":
-        time_filter = Q(scrobble__timestamp__gte=starting_day_of_current_month)
-    if filter == "year":
-        time_filter = Q(scrobble__timestamp__gte=starting_day_of_current_year)
-
-    return (
-        Track.objects.filter(time_filter)
-        .annotate(
-            num_scrobbles=Count(
-                "scrobble",
-                filter=Q(scrobble__played_to_completion=True),
-                distinct=True,
-            )
-        )
-        .order_by("-num_scrobbles")[:limit]
-    )
+    media_model = apps.get_model(app_label='music', model_name=media_type)
 
 
+    period_queries = {
+        'today': {'scrobble__timestamp__gte': start_of_today},
+        'week': {'scrobble__timestamp__gte': start_day_of_week},
+        'month': {'scrobble__timestamp__gte': start_day_of_month},
+        'year': {'scrobble__timestamp__gte': start_day_of_year},
+        'all': {},
+    }
 
 
-def top_artists(
-    user: "User", filter: str = "today", limit: int = 15
-) -> List["Artist"]:
-    time_filter = Q(track__scrobble__timestamp__gte=START_OF_TODAY)
-    if filter == "week":
-        time_filter = Q(
-            track__scrobble__timestamp__gte=STARTING_DAY_OF_CURRENT_WEEK
-        )
-    if filter == "month":
-        time_filter = Q(
-            track__scrobble__timestamp__gte=STARTING_DAY_OF_CURRENT_MONTH
-        )
-    if filter == "year":
-        time_filter = Q(
-            track__scrobble__timestamp__gte=STARTING_DAY_OF_CURRENT_YEAR
+    time_filter = Q()
+    completion_filter = Q(
+        scrobble__user=user, scrobble__played_to_completion=True
+    )
+    user_filter = Q(scrobble__user=user)
+    count_field = "scrobble"
+
+    if media_type == "Artist":
+        for period, query_dict in period_queries.items():
+            period_queries[period] = {
+                "track__" + k: v for k, v in query_dict.items()
+            }
+        completion_filter = Q(
+            track__scrobble__user=user,
+            track__scrobble__played_to_completion=True,
         )
         )
+        count_field = "track__scrobble"
+        user_filter = Q(track__scrobble__user=user)
+
+    time_filter = Q(**period_queries[chart_period])
 
 
     return (
     return (
-        Artist.objects.filter(time_filter)
+        media_model.objects.filter(user_filter, time_filter)
         .annotate(
         .annotate(
             num_scrobbles=Count(
             num_scrobbles=Count(
-                "track__scrobble",
-                filter=Q(track__scrobble__played_to_completion=True),
+                count_field,
+                filter=completion_filter,
                 distinct=True,
                 distinct=True,
             )
             )
         )
         )
-        .order_by("-num_scrobbles")
+        .order_by("-num_scrobbles")[:limit]
     )
     )