Update API to be more complete

This commit is contained in:
2023-02-20 17:08:54 -05:00
parent 2e98850494
commit cf9da39967
22 changed files with 302 additions and 44 deletions

View File

@ -0,0 +1,14 @@
from books.models import Author, Book
from rest_framework import serializers
class AuthorSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Author
fields = "__all__"
class BookSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Book
fields = "__all__"

View File

@ -0,0 +1,19 @@
from rest_framework import permissions, viewsets
from books.api.serializers import (
AuthorSerializer,
BookSerializer,
)
from books.models import Author, Book
class AuthorViewSet(viewsets.ModelViewSet):
queryset = Author.objects.all().order_by('-created')
serializer_class = AuthorSerializer
permission_classes = [permissions.IsAuthenticated]
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all().order_by('-created')
serializer_class = BookSerializer
permission_classes = [permissions.IsAuthenticated]

View File

@ -8,7 +8,8 @@ from django.urls import reverse
from django_extensions.db.models import TimeStampedModel
from scrobbles.mixins import ScrobblableMixin
from vrobbler.apps.books.utils import lookup_book_from_openlibrary
from books.utils import lookup_book_from_openlibrary
from scrobbles.utils import get_scrobbles_for_media
logger = logging.getLogger(__name__)
User = get_user_model()
@ -66,3 +67,7 @@ class Book(ScrobblableMixin):
logger.warn(f"{self} has no pages, no completion percentage")
return 0
return int(self.pages * (self.COMPLETION_PERCENT / 100))
def progress_for_user(self, user: User) -> int:
last_scrobble = get_scrobbles_for_media(self, user).last()
return int((last_scrobble.book_pages_read / self.pages) * 100)

View File

View File

@ -0,0 +1,20 @@
from music.models import Album, Artist, Track
from rest_framework import serializers
class ArtistSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Artist
fields = "__all__"
class AlbumSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Album
fields = "__all__"
class TrackSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Track
fields = "__all__"

View File

@ -0,0 +1,26 @@
from rest_framework import permissions, viewsets
from music.api.serializers import (
TrackSerializer,
ArtistSerializer,
AlbumSerializer,
)
from music.models import Artist, Album, Track
class ArtistViewSet(viewsets.ModelViewSet):
queryset = Artist.objects.all().order_by('-created')
serializer_class = ArtistSerializer
permission_classes = [permissions.IsAuthenticated]
class AlbumViewSet(viewsets.ModelViewSet):
queryset = Album.objects.all().order_by('-created')
serializer_class = AlbumSerializer
permission_classes = [permissions.IsAuthenticated]
class TrackViewSet(viewsets.ModelViewSet):
queryset = Track.objects.all().order_by('-created')
serializer_class = TrackSerializer
permission_classes = [permissions.IsAuthenticated]

View File

@ -0,0 +1 @@
#!/usr/bin/env python3

View File

@ -0,0 +1 @@
#!/usr/bin/env python3

View File

@ -0,0 +1,18 @@
from django.contrib.auth import get_user_model
from rest_framework import serializers
User = get_user_model()
from profiles.models import UserProfile
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
exclude = ('password',)
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = UserProfile
exclude = ('lastfm_password',)

View File

@ -0,0 +1,28 @@
from django.contrib.auth import get_user_model
from rest_framework import permissions, viewsets
from profiles.api.serializers import UserSerializer, UserProfileSerializer
from profiles.models import UserProfile
User = get_user_model()
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]
class UserProfileViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = UserProfile.objects.all().order_by('-created')
serializer_class = UserProfileSerializer
permission_classes = [permissions.IsAuthenticated]

View File

View File

@ -0,0 +1,33 @@
from rest_framework import serializers
from scrobbles.models import (
AudioScrobblerTSVImport,
KoReaderImport,
LastFmImport,
Scrobble,
)
class ScrobbleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Scrobble
fields = "__all__"
class KoReaderImportSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = KoReaderImport
fields = "__all__"
class AudioScrobblerTSVImportSerializer(
serializers.HyperlinkedModelSerializer
):
class Meta:
model = AudioScrobblerTSVImport
fields = "__all__"
class LastFmImportSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = LastFmImport
fields = "__all__"

View File

@ -0,0 +1,49 @@
from rest_framework import permissions, viewsets
from scrobbles.api.serializers import (
AudioScrobblerTSVImportSerializer,
KoReaderImportSerializer,
LastFmImportSerializer,
ScrobbleSerializer,
)
from scrobbles.models import (
AudioScrobblerTSVImport,
KoReaderImport,
Scrobble,
LastFmImport,
)
class ScrobbleViewSet(viewsets.ModelViewSet):
queryset = Scrobble.objects.all().order_by('-timestamp')
serializer_class = ScrobbleSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return super().get_queryset().filter(user=self.request.user)
class KoReaderImportViewSet(viewsets.ModelViewSet):
queryset = KoReaderImport.objects.all().order_by('-created')
serializer_class = KoReaderImportSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return super().get_queryset().filter(user=self.request.user)
class AudioScrobblerTSVImportViewSet(viewsets.ModelViewSet):
queryset = AudioScrobblerTSVImport.objects.all().order_by('-created')
serializer_class = AudioScrobblerTSVImportSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return super().get_queryset().filter(user=self.request.user)
class LastFmImportViewSet(viewsets.ModelViewSet):
queryset = LastFmImport.objects.all().order_by('-created')
serializer_class = LastFmImportSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return super().get_queryset().filter(user=self.request.user)

View File

@ -1,14 +0,0 @@
from rest_framework import serializers
from scrobbles.models import Scrobble, AudioScrobblerTSVImport
class AudioScrobblerTSVImportSerializer(serializers.ModelSerializer):
class Meta:
model = AudioScrobblerTSVImport
fields = ('tsv_file',)
class ScrobbleSerializer(serializers.ModelSerializer):
class Meta:
model = Scrobble
fields = "__all__"

View File

@ -4,7 +4,6 @@ from scrobbles import views
app_name = 'scrobbles'
urlpatterns = [
path('', views.scrobble_endpoint, name='api-list'),
path('finish/<slug:uuid>', views.scrobble_finish, name='finish'),
path('cancel/<slug:uuid>', views.scrobble_cancel, name='cancel'),
path(

View File

@ -1,10 +1,14 @@
import logging
from urllib.parse import unquote
from django.contrib.auth import get_user_model
from dateutil.parser import ParserError, parse
from django.conf import settings
from django.db import models
logger = logging.getLogger(__name__)
User = get_user_model()
def convert_to_seconds(run_time: str) -> int:
@ -103,3 +107,11 @@ def check_scrobble_for_finish(
if getattr(settings, "KEEP_DETAILED_SCROBBLE_LOGS", False):
scrobble.scrobble_log += f"\n{str(scrobble.timestamp)} - {scrobble.playback_position} - {str(scrobble.playback_position_ticks)} - {str(scrobble.percent_played)}%"
scrobble.save(update_fields=['scrobble_log'])
def get_scrobbles_for_media(media_obj, user: User) -> models.QuerySet:
from scrobbles.models import Scrobble
if media_obj.__class__.__name__ == 'Book':
media_query = models.Q(book=media_obj)
return Scrobble.objects.filter(media_query, user=user)

View File

@ -49,10 +49,7 @@ from scrobbles.scrobblers import (
mopidy_scrobble_podcast,
mopidy_scrobble_track,
)
from scrobbles.serializers import (
AudioScrobblerTSVImportSerializer,
ScrobbleSerializer,
)
from scrobbles.api import serializers
from scrobbles.tasks import (
process_koreader_import,
process_lastfm_import,
@ -215,15 +212,6 @@ def lastfm_import(request):
return HttpResponseRedirect(success_url)
@csrf_exempt
@api_view(['GET'])
def scrobble_endpoint(request):
"""List all Scrobbles, or create a new Scrobble"""
scrobble = Scrobble.objects.all()
serializer = ScrobbleSerializer(scrobble, many=True)
return Response(serializer.data)
@csrf_exempt
@permission_classes([IsAuthenticated])
@api_view(['POST'])
@ -293,7 +281,9 @@ def import_audioscrobbler_file(request):
scrobbles_created = []
# tsv_file = request.FILES[0]
file_serializer = AudioScrobblerTSVImportSerializer(data=request.data)
file_serializer = serializers.AudioScrobblerTSVImportSerializer(
data=request.data
)
if file_serializer.is_valid():
import_file = file_serializer.save()
return Response(

View File

View File

@ -0,0 +1,14 @@
from videos.models import Series, Video
from rest_framework import serializers
class SeriesSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Series
fields = "__all__"
class VideoSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Video
fields = "__all__"

View File

@ -0,0 +1,19 @@
from rest_framework import permissions, viewsets
from videos.api.serializers import (
SeriesSerializer,
VideoSerializer,
)
from videos.models import Series, Video
class SeriesViewSet(viewsets.ModelViewSet):
queryset = Series.objects.all().order_by('-created')
serializer_class = SeriesSerializer
permission_classes = [permissions.IsAuthenticated]
class VideoViewSet(viewsets.ModelViewSet):
queryset = Video.objects.all().order_by('-created')
serializer_class = VideoSerializer
permission_classes = [permissions.IsAuthenticated]

View File

@ -174,19 +174,14 @@ AUTHENTICATION_BACKENDS = [
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.AllowAny",),
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"DEFAULT_FILTER_BACKENDS": [
"django_filters.rest_framework.DjangoFilterBackend"
],
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
],
'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'vrobbler.negotiation.IgnoreClientContentNegotiation',
"PAGE_SIZE": 100,
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"PAGE_SIZE": 200,
}
LOGIN_REDIRECT_URL = "/"

View File

@ -3,17 +3,46 @@ from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import include, path
from scrobbles import urls as scrobble_urls
from music import urls as music_urls
from videos import urls as video_urls
from rest_framework import routers
from vrobbler.apps.books.api.views import AuthorViewSet, BookViewSet
from vrobbler.apps.music import urls as music_urls
from vrobbler.apps.music.api.views import (
AlbumViewSet,
ArtistViewSet,
TrackViewSet,
)
from vrobbler.apps.profiles.api.views import UserProfileViewSet, UserViewSet
from vrobbler.apps.scrobbles import urls as scrobble_urls
from vrobbler.apps.scrobbles.api.views import (
AudioScrobblerTSVImportViewSet,
KoReaderImportViewSet,
LastFmImportViewSet,
ScrobbleViewSet,
)
from vrobbler.apps.videos import urls as video_urls
from vrobbler.apps.videos.api.views import SeriesViewSet, VideoViewSet
router = routers.DefaultRouter()
router.register(r'scrobbles', ScrobbleViewSet)
router.register(r'lastfm-imports', LastFmImportViewSet)
router.register(r'tsv-imports', AudioScrobblerTSVImportViewSet)
router.register(r'koreader-imports', KoReaderImportViewSet)
router.register(r'artist', ArtistViewSet)
router.register(r'album', AlbumViewSet)
router.register(r'tracks', TrackViewSet)
router.register(r'series', SeriesViewSet)
router.register(r'videos', VideoViewSet)
router.register(r'authors', AuthorViewSet)
router.register(r'books', BookViewSet)
router.register(r'users', UserViewSet)
router.register(r'user_profiles', UserProfileViewSet)
urlpatterns = [
path('api/v1/', include(router.urls)),
path('api/v1/auth', include("rest_framework.urls")),
path("admin/", admin.site.urls),
path("accounts/", include("allauth.urls")),
# path("api-auth/", include("rest_framework.urls")),
# path("movies/", include(movies, namespace="movies")),
# path("shows/", include(shows, namespace="shows")),
path("api/v1/scrobbles/", include(scrobble_urls, namespace="scrobbles")),
path(
'manual/imdb/',
scrobbles_views.ManualScrobbleView.as_view(),