Browse Source

Fixing long play scrobbles

Colin Powell 2 năm trước cách đây
mục cha
commit
9bcd9d8bb7

+ 23 - 0
vrobbler/apps/books/migrations/0002_book_author_name_book_author_openlibrary_id.py

@@ -0,0 +1,23 @@
+# Generated by Django 4.1.5 on 2023-03-06 05:29
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("books", "0001_initial"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="book",
+            name="author_name",
+            field=models.CharField(blank=True, max_length=255, null=True),
+        ),
+        migrations.AddField(
+            model_name="book",
+            name="author_openlibrary_id",
+            field=models.CharField(blank=True, max_length=255, null=True),
+        ),
+    ]

+ 20 - 0
vrobbler/apps/books/migrations/0003_book_cover.py

@@ -0,0 +1,20 @@
+# Generated by Django 4.1.5 on 2023-03-06 05:31
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("books", "0002_book_author_name_book_author_openlibrary_id"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="book",
+            name="cover",
+            field=models.ImageField(
+                blank=True, null=True, upload_to="books/covers/"
+            ),
+        ),
+    ]

+ 19 - 0
vrobbler/apps/books/urls.py

@@ -0,0 +1,19 @@
+from django.urls import path
+from books import views
+
+app_name = "books"
+
+
+urlpatterns = [
+    path("book/", views.BookListView.as_view(), name="book_list"),
+    path(
+        "book/<slug:slug>/",
+        views.BookDetailView.as_view(),
+        name="book_detail",
+    ),
+    path(
+        "author/<slug:slug>/",
+        views.AuthorDetailView.as_view(),
+        name="author_detail",
+    ),
+]

+ 17 - 0
vrobbler/apps/books/views.py

@@ -0,0 +1,17 @@
+from django.views import generic
+from books.models import Book, Author
+
+
+class BookListView(generic.ListView):
+    model = Book
+    paginate_by = 20
+
+
+class BookDetailView(generic.DetailView):
+    model = Book
+    slug_field = "uuid"
+
+
+class AuthorDetailView(generic.DetailView):
+    model = Author
+    slug_field = "uuid"

+ 22 - 0
vrobbler/apps/scrobbles/migrations/0027_remove_scrobble_videogame_minutes_played_and_more.py

@@ -0,0 +1,22 @@
+# Generated by Django 4.1.5 on 2023-03-06 02:52
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("scrobbles", "0026_scrobble_video_game"),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name="scrobble",
+            name="videogame_minutes_played",
+        ),
+        migrations.AlterField(
+            model_name="scrobble",
+            name="playback_position",
+            field=models.CharField(blank=True, max_length=10, null=True),
+        ),
+    ]

+ 21 - 0
vrobbler/apps/scrobbles/migrations/0028_scrobble_video_game_minutes_played.py

@@ -0,0 +1,21 @@
+# Generated by Django 4.1.5 on 2023-03-06 05:04
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        (
+            "scrobbles",
+            "0027_remove_scrobble_videogame_minutes_played_and_more",
+        ),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="scrobble",
+            name="video_game_minutes_played",
+            field=models.IntegerField(blank=True, null=True),
+        ),
+    ]

BIN
vrobbler/apps/scrobbles/static/images/hltb.webp


BIN
vrobbler/apps/scrobbles/static/images/igdb-logo.png


+ 23 - 0
vrobbler/apps/videogames/migrations/0006_videogame_summary_alter_videogame_platforms.py

@@ -0,0 +1,23 @@
+# Generated by Django 4.1.5 on 2023-03-06 02:52
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("videogames", "0005_rename_platform_videogame_platforms"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="videogame",
+            name="summary",
+            field=models.TextField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name="videogame",
+            name="platforms",
+            field=models.ManyToManyField(to="videogames.videogameplatform"),
+        ),
+    ]

+ 0 - 0
vrobbler/apps/videogames/templatetags/__init__.py


+ 16 - 0
vrobbler/apps/videogames/templatetags/naturalduration.py

@@ -0,0 +1,16 @@
+from django import template
+
+register = template.Library()
+
+
+@register.filter
+def natural_duration(value):
+    value = int(value)
+    hours = int(value / 60)
+    minutes = value - (hours * 60)
+    value_str = ""
+    if minutes:
+        value_str = f"{minutes} minutes"
+    if hours:
+        value_str = f"{hours} hours, " + value_str
+    return value_str

+ 57 - 0
vrobbler/templates/books/book_detail.html

@@ -0,0 +1,57 @@
+{% extends "base_list.html" %}
+{% load mathfilters %}
+{% load static %}
+{% load naturalduration %}
+
+{% block title %}{{object.title}}{% endblock %}
+
+{% block lists %}
+
+<div class="row">
+
+    {% if object.cover%}
+    <p style="float:left; width:402px; padding:0; border: 1px solid #ccc">
+        <img src="{{object.cover.url}}" width=400 />
+    </p>
+    {% endif %}
+    <div style="float:left; width:600px; margin-left:10px; ">
+        {% if object.summary %}
+        <p>{{object.summary|safe|linebreaks|truncatewords:160}}</p>
+        <hr />
+        {% endif %}
+        <p style="float:right;">
+            <a href="{{object.openlibrary_link}}"><img src="{% static " images/openlibrary-logo.png" %}" width=35></a>
+            <a href="{{object.amazon_link}}"><img src="{% static " images/amazon-logo.png" %}" width=35></a>
+        </p>
+    </div>
+</div>
+<div class="row">
+    <p>{{object.scrobble_set.count}} scrobbles</p>
+    <p><a href="">Start playing</a></p>
+</div>
+<div class="row">
+    <div class="col-md">
+        <h3>Last scrobbles</h3>
+        <div class="table-responsive">
+            <table class="table table-striped table-sm">
+                <thead>
+                    <tr>
+                        <th scope="col">Date</th>
+                        <th scope="col">Duration</th>
+                        <th scope="col">Authors</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    {% for scrobble in object.scrobble_set.all|dictsortreversed:"timestamp" %}
+                    <tr>
+                        <td>{{scrobble.timestamp}}</td>
+                        <td>{% if scrobble.in_progress %}Now playing{% else %}{{scrobble.playback_position|natural_duration}}{% endif %}</td>
+                        <td>{% for author in scrobble.book.authors.all %}<a href="{{author.get_absolute_url}}">{{author}}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td>
+                    </tr>
+                    {% endfor %}
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>
+{% endblock %}

+ 57 - 0
vrobbler/templates/videogames/videogame_detail.html

@@ -0,0 +1,57 @@
+{% extends "base_list.html" %}
+{% load mathfilters %}
+{% load static %}
+{% load naturalduration %}
+
+{% block title %}{{object.title}}{% endblock %}
+
+{% block lists %}
+
+<div class="row">
+
+    {% if object.hltb_cover%}
+    <p style="float:left; width:402px; padding:0; border: 1px solid #ccc">
+        <img src="{{object.hltb_cover.url}}" width=400 />
+    </p>
+    {% endif %}
+    <div style="float:left; width:600px; margin-left:10px; ">
+        {% if object.summary %}
+        <p>{{object.summary|safe|linebreaks|truncatewords:160}}</p>
+        <hr/>
+        {% endif %}
+        <p style="float:right;">
+            <a href="{{object.igdb_link}}"><img src="{% static "images/igdb-logo.png" %}" width=35></a>
+            <a href="{{object.hltb_link}}"><img style="background: black;" src="{% static "images/hltb.webp" %}" width=35></a>
+        </p>
+    </div>
+</div>
+<div class="row">
+    <p>{{object.scrobble_set.count}} scrobbles</p>
+    <p><a href="">Start playing</a></p>
+</div>
+<div class="row">
+    <div class="col-md">
+        <h3>Last scrobbles</h3>
+        <div class="table-responsive">
+            <table class="table table-striped table-sm">
+            <thead>
+                <tr>
+                    <th scope="col">Date</th>
+                    <th scope="col">Duration</th>
+                    <th scope="col">Platforms</th>
+                </tr>
+            </thead>
+            <tbody>
+                {% for scrobble in object.scrobble_set.all|dictsortreversed:"timestamp" %}
+                <tr>
+                    <td>{{scrobble.timestamp}}</td>
+                    <td>{% if scrobble.in_progress %}Now playing{% else %}{{scrobble.playback_position|natural_duration}}{% endif %}</td>
+                    <td>{% for platform in scrobble.video_game.platforms.all %}<a href="{{platform.get_absolute_url}}">{{platform}}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td>
+                </tr>
+                {% endfor %}
+            </tbody>
+            </table>
+        </div>
+    </div>
+</div>
+{% endblock %}