[charts] Add TV charts

This commit is contained in:
2026-03-11 23:53:08 -04:00
parent 118e208a36
commit 0e5d8e6b2f
4 changed files with 313 additions and 2 deletions

View File

@ -89,6 +89,7 @@ def live_charts(
media_type: str = "Track",
chart_period: str = "all",
limit: int = 15,
app_label: str = "music",
) -> QuerySet:
now = timezone.now()
tzinfo = now.tzinfo
@ -106,7 +107,7 @@ def live_charts(
start_day_of_month = now.replace(day=1)
start_day_of_year = now.replace(month=1, day=1)
media_model = apps.get_model(app_label="music", model_name=media_type)
media_model = apps.get_model(app_label=app_label, model_name=media_type)
period_queries = {
"today": {"scrobble__timestamp__gte": start_of_today},
@ -154,3 +155,60 @@ def live_charts(
def artist_scrobble_count(artist_id: int, filter: str = "today") -> int:
return Scrobble.objects.filter(track__artist=artist_id).count()
def live_tv_charts(
user: "User",
chart_period: str = "all",
limit: int = 15,
) -> QuerySet:
from django.db.models import OuterRef, Subquery
from videos.models import Video, Series
now = timezone.now()
tzinfo = now.tzinfo
now = now.date()
if user.is_authenticated:
now = now_user_timezone(user.profile)
tzinfo = now.tzinfo
seven_days_ago = now - timedelta(days=7)
thirty_days_ago = now - timedelta(days=30)
start_of_today = datetime.combine(now, datetime.min.time(), tzinfo)
start_day_of_week = start_of_today - timedelta(days=now.today().isoweekday() % 7)
start_day_of_month = now.replace(day=1)
start_day_of_year = now.replace(month=1, day=1)
period_queries = {
"today": Q(timestamp__gte=start_of_today),
"week": Q(timestamp__gte=start_day_of_week),
"last7": Q(timestamp__gte=seven_days_ago),
"last30": Q(timestamp__gte=thirty_days_ago),
"month": Q(timestamp__gte=start_day_of_month),
"year": Q(timestamp__gte=start_day_of_year),
"all": Q(),
}
time_filter = period_queries[chart_period]
completion_filter = Q(
user=user,
played_to_completion=True,
video__video_type=Video.VideoType.TV_EPISODE,
)
scrobble_counts = (
Scrobble.objects.filter(
completion_filter,
time_filter,
video__tv_series=OuterRef("pk"),
)
.values("video__tv_series")
.annotate(c=Count("id"))
.values("c")
)
return (
Series.objects.annotate(num_scrobbles=Subquery(scrobble_counts))
.filter(num_scrobbles__gt=0)
.order_by("-num_scrobbles")[:limit]
)