diff --git a/vrobbler/apps/scrobbles/models.py b/vrobbler/apps/scrobbles/models.py
index b5adee3..8a49a90 100644
--- a/vrobbler/apps/scrobbles/models.py
+++ b/vrobbler/apps/scrobbles/models.py
@@ -604,45 +604,39 @@ class Scrobble(TimeStampedModel):
@classmethod
def for_year(cls, user, year):
- return cls.objects.filter(timestamp__year=year, user=user)
+ return cls.objects.filter(timestamp__year=year, user=user).order_by(
+ "-timestamp"
+ )
@classmethod
def for_month(cls, user, year, month):
return cls.objects.filter(
timestamp__year=year, timestamp__month=month, user=user
- )
+ ).order_by("-timestamp")
@classmethod
- def for_day(cls, user, year, day, month):
+ def for_day(cls, user, year, month, day):
return cls.objects.filter(
timestamp__year=year,
timestamp__month=month,
timestamp__day=day,
user=user,
- )
-
- @classmethod
- def for_day_dict(
- cls, user_id: int, year: int, month: int, day: int
- ) -> dict:
- scrobbles_by_type = defaultdict(list)
- scrobbles = cls.objects.filter(
- timestamp__year=year,
- timestamp__month=month,
- timestamp__day=day,
- user_id=user_id,
).order_by("-timestamp")
- for scrobble in scrobbles:
- scrobbles_by_type[scrobble.media_type].append(scrobble)
-
- return scrobbles_by_type
-
@classmethod
def for_week(cls, user, year, week):
return cls.objects.filter(
timestamp__year=year, timestamp__week=week, user=user
- )
+ ).order_by("-timestamp")
+
+ @classmethod
+ def as_dict_by_type(cls, scrobble_qs: models.QuerySet) -> dict:
+ scrobbles_by_type = defaultdict(list)
+
+ for scrobble in scrobble_qs:
+ scrobbles_by_type[scrobble.media_type].append(scrobble)
+
+ return scrobbles_by_type
@classmethod
def in_progress_for_user(cls, user_id: int) -> models.QuerySet:
@@ -847,7 +841,10 @@ class Scrobble(TimeStampedModel):
@property
def elapsed_time(self) -> int | None:
if self.played_to_completion:
- return self.playback_position_seconds
+ if self.playback_position_seconds:
+ return self.playback_position_seconds
+ if self.media_obj.run_time_seconds:
+ return self.media_obj.run_time_seconds
return (timezone.now() - self.timestamp).seconds
@property
diff --git a/vrobbler/apps/scrobbles/views.py b/vrobbler/apps/scrobbles/views.py
index be54607..48d16c5 100644
--- a/vrobbler/apps/scrobbles/views.py
+++ b/vrobbler/apps/scrobbles/views.py
@@ -2,9 +2,9 @@ import calendar
import json
import logging
from datetime import datetime, timedelta
+from dateutil.relativedelta import relativedelta
import pendulum
-from pendulum.parsing.exceptions import ParserError
import pytz
from django.apps import apps
from django.contrib import messages
@@ -109,20 +109,92 @@ class RecentScrobbleList(ListView):
user = self.request.user
data["date"] = ""
if user.is_authenticated:
- date = self.request.GET.get("date", "")
- today = timezone.localtime(timezone.now())
+ self.queryset = self.get_queryset().filter(user=user)
user_id = self.request.user.id
- year = today.year
- month = today.month
- day = today.day
- if date:
+
+ today = timezone.localtime(timezone.now())
+ date_str = self.request.GET.get("date", "")
+ date = today
+ if date_str:
try:
- data["date"] = pendulum.parse(date)
- year, month, day = date.split("-")
+ date = pendulum.parse(date_str)
except:
pass
-
- data = data | Scrobble.for_day_dict(user_id, year, month, day)
+ if date_str:
+ if date_str == "this_week" or "-W" in date_str:
+ next_date = date + timedelta(weeks=+2)
+ prev_date = date + timedelta(weeks=-1)
+ if date.isocalendar()[1] < today.isocalendar()[1]:
+ data[
+ "next_link"
+ ] = f"?date={next_date.strftime('%Y-W%W')}"
+ data["prev_link"] = f"?date={prev_date.strftime('%Y-W%W')}"
+ data[
+ "title"
+ ] = f"Week {date.strftime('%-W')} of {date.year}"
+ data = data | Scrobble.as_dict_by_type(
+ Scrobble.for_week(
+ user_id, date.year, date.isocalendar()[1]
+ )
+ )
+ elif date_str == "this_month" or date_str.count("-") == 1:
+ next_date = date + relativedelta(months=1)
+ prev_date = date + relativedelta(months=-1)
+ if date.month < today.month:
+ data[
+ "next_link"
+ ] = f"?date={next_date.strftime('%Y-%m')}"
+ data["title"] = f"{date.strftime('%B %Y')}"
+ data["prev_link"] = f"?date={prev_date.strftime('%Y-%m')}"
+ data = data | Scrobble.as_dict_by_type(
+ Scrobble.for_month(user_id, date.year, date.month)
+ )
+ elif date_str == "today" or date_str.count("-") == 2:
+ next_date = date + timedelta(days=1)
+ prev_date = date - timedelta(days=1)
+ data[
+ "prev_link"
+ ] = f"?date={prev_date.strftime('%Y-%m-%d')}"
+ if date < today:
+ data[
+ "next_link"
+ ] = f"?date={next_date.strftime('%Y-%m-%d')}"
+ if date == today:
+ data["title"] = "Today"
+ else:
+ data["title"] = f"{date.strftime('%Y-%m-%d')}"
+ data[
+ "today_link"
+ ] = f"?date={today.strftime('%Y-%m-%d')}"
+ data = data | Scrobble.as_dict_by_type(
+ Scrobble.for_day(
+ user_id, date.year, date.month, date.day
+ )
+ )
+ elif date_str == "this_year" or date_str.count("-") == 0:
+ next_date = date + relativedelta(years=+1)
+ prev_date = date + relativedelta(years=-1)
+ data["next_link"] = ""
+ if date.year < today.year:
+ data["title"] = f"{date.strftime('%Y')}"
+ data["next_link"] = f"?date={next_date.year}"
+ data["title"] = f"{date.year}"
+ data["prev_link"] = f"?date={prev_date.year}"
+ data = data | Scrobble.as_dict_by_type(
+ Scrobble.for_year(user_id, date.year)
+ )
+ else:
+ next_date = today - timedelta(days=1)
+ prev_date = today - timedelta(days=1)
+ data["title"] = "Today"
+ data["next_link"] = ""
+ data["prev_link"] = f"?date={prev_date.strftime('%Y-%m-%d')}"
+ data = data | Scrobble.as_dict_by_type(
+ Scrobble.for_day(user_id, date.year, date.month, date.day)
+ )
+ data[
+ "today_link"
+ ] = "" # f"?date={today.strftime('%Y-%m-%d')}"
data["active_imports"] = AudioScrobblerTSVImport.objects.filter(
processing_started__isnull=False,
@@ -139,9 +211,7 @@ class RecentScrobbleList(ListView):
return data
def get_queryset(self):
- return Scrobble.objects.filter(
- track__isnull=False, in_progress=False
- ).order_by("-timestamp")[:15]
+ return Scrobble.objects.all().order_by("-timestamp")
class ScrobbleLongPlaysView(TemplateView):
@@ -453,6 +523,7 @@ def gps_webhook(request):
return Response({"scrobble_id": scrobble.id}, status=status.HTTP_200_OK)
+
@csrf_exempt
@api_view(["POST"])
def emacs_webhook(request):
@@ -474,9 +545,9 @@ def emacs_webhook(request):
if request.user.id:
user_id = request.user.id
- #scrobble = gpslogger_scrobble_location(data_dict, user_id)
+ # scrobble = gpslogger_scrobble_location(data_dict, user_id)
- #if not scrobble:
+ # if not scrobble:
# return Response({}, status=status.HTTP_200_OK)
return Response({"post_data": post_data}, status=status.HTTP_200_OK)
diff --git a/vrobbler/templates/scrobbles/_last_scrobbles.html b/vrobbler/templates/scrobbles/_last_scrobbles.html
index f326b41..fe50ae8 100644
--- a/vrobbler/templates/scrobbles/_last_scrobbles.html
+++ b/vrobbler/templates/scrobbles/_last_scrobbles.html
@@ -1,305 +1,82 @@
{% load humanize %}
{% load naturalduration %}
-
-
Today {{counts.today}} | This Week {{counts.week}} | This Month {{counts.month}} | This Year {{counts.year}} | All Time {{counts.alltime}}
+
+
+
Today {{counts.today}} | This Week {{counts.week}} | This Month {{counts.month}} | This Year {{counts.year}} | All Time {{counts.alltime}}
+
-
+
{% if Track %}
-
+
Music
+ {% with scrobbles=Track %}
+ {% include "scrobbles/_scrobble_table.html" %}
+ {% endwith %}
+ {% endif %}
+
+
+
+ {% if Task %}
+
Latest tasks
+ {% with scrobbles=Task %}
+ {% include "scrobbles/_scrobble_table.html" %}
+ {% endwith %}
{% endif %}
{% if Video %}
-
- {% endif %}
-
- {% if SportEvent %}
-
-
Latest Sports
-
-
-
-
- | Date |
- Title |
- Round |
- League |
- Time watched |
-
-
-
- {% for scrobble in SportEvent %}
-
- | {% if scrobble.in_progress %}{{scrobble.media_obj.strings.verb}} now | Finish{% else %}{{scrobble.timestamp|naturaltime}}{% endif %} |
- {{scrobble.sport_event.title}} |
- {{scrobble.sport_event.round.name}} |
- {{scrobble.sport_event.round.season.league}} |
- {{scrobble.elapsed_time|natural_duration}} |
-
- {% endfor %}
-
-
-
-
- {% endif %}
-
- {% if PodcastEpisode %}
-
-
-
-
-
- | Date |
- Title |
- Podcast |
-
-
-
- {% for scrobble in PodcastEpisode %}
-
- | {% if scrobble.in_progress %}{{scrobble.media_obj.strings.verb}} now | Finish{% else %}{{scrobble.timestamp|naturaltime}}{% endif %} |
- {{scrobble.timestamp|naturaltime}} |
- {{scrobble.podcast_episode.title}} |
- {{scrobble.podcast_episode.podcast}} |
-
- {% endfor %}
-
-
-
-
- {% endif %}
-
- {% if VideoGame %}
-
Video games
-
-
-
-
-
- | Date |
- Cover |
- Title |
- Time played |
- Percent complete |
-
-
-
- {% for scrobble in VideoGame %}
-
- | {% if scrobble.in_progress %}{{scrobble.media_obj.strings.verb}} now | Finish{% else %}{{scrobble.timestamp|naturaltime}}{% endif %} |
- {% if scrobble.media_obj.hltb_cover %}
-  |
- {% endif %}
- {{scrobble.media_obj.title}} |
- {{scrobble.elapsed_time|natural_duration}} |
- {{scrobble.percent_played}} |
-
- {% endfor %}
-
-
-
-
- {% endif %}
-
-
- {% if BoardGame %}
-
Board games
-
-
-
-
-
- | Date |
- Cover |
- Title |
- Time played |
-
-
-
- {% for scrobble in BoardGame %}
-
- | {% if scrobble.in_progress %}{{scrobble.media_obj.strings.verb}} now | Finish{% else %}{{scrobble.timestamp|naturaltime}}{% endif %} |
-  |
- {{scrobble.media_obj.title}} |
- {{scrobble.elapsed_time|natural_duration}} |
-
- {% endfor %}
-
-
-
-
+
Videos
+ {% with scrobbles=Video %}
+ {% include "scrobbles/_scrobble_table.html" %}
+ {% endwith %}
{% endif %}
{% if WebPage %}
Web pages
-
-
-
-
-
- | Date |
- Title |
- Time browsing |
-
-
-
- {% for scrobble in WebPage %}
-
- | {% if scrobble.in_progress %}{{scrobble.media_obj.strings.verb}} now | Finish{% else %}{{scrobble.timestamp|naturaltime}}{% endif %} |
- {{scrobble.media_obj.title}} |
- {{scrobble.elapsed_time|natural_duration}} |
-
- {% endfor %}
-
-
-
-
+ {% with scrobbles=WebPage %}
+ {% include "scrobbles/_scrobble_table.html" %}
+ {% endwith %}
+ {% endif %}
+
+ {% if SportEvent %}
+
Sports
+ {% with scrobbles=SportEvent %}
+ {% include "scrobbles/_scrobble_table.html" %}
+ {% endwith %}
+ {% endif %}
+
+ {% if PodcastEpisode %}
+
Latest podcasts
+ {% with scrobbles=PodcastEpisode %}
+ {% include "scrobbles/_scrobble_table.html" %}
+ {% endwith %}
+ {% endif %}
+
+ {% if VideoGame %}
+
Video games
+ {% with scrobbles=VideoGame %}
+ {% include "scrobbles/_scrobble_table.html" %}
+ {% endwith %}
+ {% endif %}
+
+ {% if BoardGame %}
+
Board games
+ {% with scrobbles=BoardGame %}
+ {% include "scrobbles/_scrobble_table.html" %}
+ {% endwith %}
{% endif %}
{% if Beer %}
Beers
-
-
-
-
-
- | Date |
- Cover |
- Title |
- Time drinking |
-
-
-
- {% for scrobble in Beer %}
-
- | {% if scrobble.in_progress %}{{scrobble.media_obj.strings.verb}} now | Finish{% else %}{{scrobble.timestamp|naturaltime}}{% endif %} |
-  |
- {{scrobble.media_obj.title}} |
- {{scrobble.elapsed_time|natural_duration}} |
-
- {% endfor %}
-
-
-
-
+ {% with scrobbles=Beer %}
+ {% include "scrobbles/_scrobble_table.html" %}
+ {% endwith %}
{% endif %}
{% if Book %}
Books
-
-
-
-
-
- | Date |
- Cover |
- Title |
- Time reading |
-
-
-
- {% for scrobble in Book %}
-
- | {% if scrobble.in_progress %}{{scrobble.media_obj.strings.verb}} now | Finish{% else %}{{scrobble.timestamp|naturaltime}}{% endif %} |
-  |
- {{scrobble.media_obj.title}} |
- {{scrobble.elapsed_time|natural_duration}} |
-
- {% endfor %}
-
-
-
-
- {% endif %}
-
- {% if Task %}
-
-
-
-
-
- | Date |
- Title |
- Time doing |
-
-
-
- {% for scrobble in Task %}
-
- | {% if scrobble.in_progress %}{{scrobble.media_obj.strings.verb}} now | Finish{% else %}{{scrobble.timestamp|naturaltime}}{% endif %} |
- {{scrobble.media_obj.title}} |
- {{scrobble.elapsed_time|natural_duration}} |
-
- {% endfor %}
-
-
-
-
+ {% with scrobbles=Book %}
+ {% include "scrobbles/_scrobble_table.html" %}
+ {% endwith %}
{% endif %}
diff --git a/vrobbler/templates/scrobbles/_row.html b/vrobbler/templates/scrobbles/_row.html
new file mode 100644
index 0000000..54a1fda
--- /dev/null
+++ b/vrobbler/templates/scrobbles/_row.html
@@ -0,0 +1,7 @@
+{% load humanize %}
+{% load naturalduration %}
+
+ | {% if scrobble.in_progress %}{{scrobble.media_obj.strings.verb}} now | Finish{% else %}{{scrobble.timestamp|naturaltime}}{% endif %} |
+ {{scrobble.media_obj|truncatechars_html:50}} |
+ {{scrobble.elapsed_time|natural_duration}} |
+
diff --git a/vrobbler/templates/scrobbles/_scrobble_table.html b/vrobbler/templates/scrobbles/_scrobble_table.html
new file mode 100644
index 0000000..42f3f3b
--- /dev/null
+++ b/vrobbler/templates/scrobbles/_scrobble_table.html
@@ -0,0 +1,22 @@
+{% load humanize %}
+{% load naturalduration %}
+
+
+
+
+
+
+ | Date |
+ Title |
+ Time |
+
+
+
+ {% for scrobble in scrobbles %}
+ {% include "scrobbles/_row.html" %}
+ {% endfor %}
+
+
+
+
diff --git a/vrobbler/templates/scrobbles/scrobble_list.html b/vrobbler/templates/scrobbles/scrobble_list.html
index 80f941b..db3b8e5 100644
--- a/vrobbler/templates/scrobbles/scrobble_list.html
+++ b/vrobbler/templates/scrobbles/scrobble_list.html
@@ -49,9 +49,28 @@
-
{% if date %}{{date|naturaltime}}{% else %}Today{% endif %}
+
{% if date %}{{date|naturaltime}}{% else %}{{title}}{% endif %}