def tracks(self, request, *args, **kwargs): playlist = self.get_object() plts = playlist.playlist_tracks.all().for_nested_serialization( music_utils.get_actor_from_request(request)) serializer = serializers.PlaylistTrackSerializer(plts, many=True) data = {"count": len(plts), "results": serializer.data} return Response(data, status=200)
def get_album_list2(self, request, *args, **kwargs): queryset = music_models.Album.objects.with_tracks_count().order_by( "artist__name") data = request.GET or request.POST filterset = filters.AlbumList2FilterSet(data, queryset=queryset) queryset = filterset.qs actor = utils.get_actor_from_request(request) queryset = queryset.playable_by(actor) try: offset = int(data["offset"]) except (TypeError, KeyError, ValueError): offset = 0 try: size = int(data["size"]) except (TypeError, KeyError, ValueError): size = 50 size = min(size, 500) queryset = queryset[offset:offset + size] data = { "albumList2": { "album": serializers.get_album_list2_data(queryset) } } return response.Response(data)
def search3(self, request, *args, **kwargs): data = request.GET or request.POST query = str(data.get("query", "")).replace("*", "") actor = utils.get_actor_from_request(request) conf = [ { "subsonic": "artist", "search_fields": ["name"], "queryset": (music_models.Artist.objects.with_albums_count().values( "id", "_albums_count", "name")), "serializer": lambda qs: [serializers.get_artist_data(a) for a in qs], }, { "subsonic": "album", "search_fields": ["title"], "queryset": (music_models.Album.objects.with_tracks_count().select_related( "artist")), "serializer": serializers.get_album_list2_data, }, { "subsonic": "song", "search_fields": ["title"], "queryset": (music_models.Track.objects.prefetch_related( "uploads").select_related("album__artist")), "serializer": serializers.get_song_list_data, }, ] payload = {"searchResult3": {}} for c in conf: offsetKey = "{}Offset".format(c["subsonic"]) countKey = "{}Count".format(c["subsonic"]) try: offset = int(data[offsetKey]) except (TypeError, KeyError, ValueError): offset = 0 try: size = int(data[countKey]) except (TypeError, KeyError, ValueError): size = 20 size = min(size, 100) queryset = c["queryset"] if query: queryset = c["queryset"].filter( utils.get_query(query, c["search_fields"])) queryset = queryset.playable_by(actor) queryset = common_utils.order_for_search(queryset, c["search_fields"][0]) queryset = queryset[offset:offset + size] payload["searchResult3"][c["subsonic"]] = c["serializer"](queryset) return response.Response(payload)
def get_songs_by_genre(self, request, *args, **kwargs): data = request.GET or request.POST actor = utils.get_actor_from_request(request) queryset = music_models.Track.objects.all().exclude( moderation_filters.get_filtered_content_query( moderation_filters.USER_FILTER_CONFIG["TRACK"], request.user)) queryset = queryset.playable_by(actor) try: offset = int(data.get("offset", 0)) except (TypeError, ValueError): offset = 0 try: size = int(data["count"] ) # yep. Some endpoints have size, other have count… except (TypeError, KeyError, ValueError): size = 50 genre = data.get("genre") queryset = (queryset.playable_by(actor).filter( Q(tagged_items__tag__name=genre) | Q(artist__tagged_items__tag__name=genre) | Q(album__artist__tagged_items__tag__name=genre) | Q(album__tagged_items__tag__name=genre)).prefetch_related( "uploads").distinct().order_by("-creation_date") [offset:offset + size]) data = { "songsByGenre": { "song": serializers.GetSongSerializer(queryset, many=True).data } } return response.Response(data)
def get_indexes(self, request, *args, **kwargs): artists = music_models.Artist.objects.all().playable_by( utils.get_actor_from_request(request)) data = serializers.GetArtistsSerializer(artists).data payload = {"indexes": data} return response.Response(payload, status=200)
def get_queryset(self): return self.queryset.filter( fields.privacy_level_query( self.request.user, lookup_field="playlist__privacy_level", user_field="playlist__user", )).for_nested_serialization( music_utils.get_actor_from_request(self.request))
def get_queryset(self): queryset = super().get_queryset() queryset = queryset.filter( fields.privacy_level_query(self.request.user, "user__privacy_level")) tracks = Track.objects.with_playable_uploads( music_utils.get_actor_from_request(self.request)).select_related( "artist", "album__artist", "attributed_to") return queryset.prefetch_related(Prefetch("track", queryset=tracks))
def get_indexes(self, request, *args, **kwargs): artists = (music_models.Artist.objects.all().exclude( moderation_filters.get_filtered_content_query( moderation_filters.USER_FILTER_CONFIG["ARTIST"], request.user)).playable_by( utils.get_actor_from_request(request))) data = serializers.GetArtistsSerializer(artists).data payload = {"indexes": data} return response.Response(payload, status=200)
def tracks(self, request, *args, **kwargs): radio = self.get_object() tracks = radio.get_candidates().for_nested_serialization() actor = music_utils.get_actor_from_request(self.request) tracks = tracks.with_playable_uploads(actor) tracks = tracks.playable_by(actor) page = self.paginate_queryset(tracks) if page is not None: serializer = TrackSerializer(page, many=True) return self.get_paginated_response(serializer.data)
def add(self, request, *args, **kwargs): playlist = self.get_object() serializer = serializers.PlaylistAddManySerializer(data=request.data) serializer.is_valid(raise_exception=True) try: plts = playlist.insert_many(serializer.validated_data["tracks"]) except exceptions.ValidationError as e: payload = {"playlist": e.detail} return Response(payload, status=400) ids = [p.id for p in plts] plts = (models.PlaylistTrack.objects.filter( pk__in=ids).order_by("index").for_nested_serialization( music_utils.get_actor_from_request(request))) serializer = serializers.PlaylistTrackSerializer(plts, many=True) data = {"count": len(plts), "results": serializer.data} return Response(data, status=201)
def inner(self, request, *args, **kwargs): data = request.GET or request.POST try: raw_value = data[field] except KeyError: return response.Response({ "error": { "code": 10, "message": "required parameter '{}' not present".format(field), } }) try: value = cast(raw_value) except (ValueError, TypeError, ValidationError): return response.Response({ "error": { "code": 0, "message": 'For input string "{}"'.format(raw_value), } }) qs = queryset if hasattr(qs, "__call__"): qs = qs(request) if filter_playable: actor = utils.get_actor_from_request(request) qs = qs.playable_by(actor).distinct() try: obj = qs.get(**{model_field: value}) except qs.model.DoesNotExist: return response.Response({ "error": { "code": 70, "message": "{} not found".format(qs.model.__class__.__name__), } }) kwargs["obj"] = obj return func(self, request, *args, **kwargs)
def get_random_songs(self, request, *args, **kwargs): data = request.GET or request.POST actor = utils.get_actor_from_request(request) queryset = music_models.Track.objects.all().exclude( moderation_filters.get_filtered_content_query( moderation_filters.USER_FILTER_CONFIG["TRACK"], request.user)) queryset = queryset.playable_by(actor) try: size = int(data["size"]) except (TypeError, KeyError, ValueError): size = 50 queryset = (queryset.playable_by(actor).prefetch_related( "uploads").order_by("?")[:size]) data = { "randomSongs": { "song": serializers.GetSongSerializer(queryset, many=True).data } } return response.Response(data)
def get_queryset(self): queryset = super().get_queryset() actor = music_utils.get_actor_from_request(self.request) return queryset.playable_by(actor)
def get_queryset(self): return self.queryset.filter( fields.privacy_level_query(self.request.user)).with_playable_plts( music_utils.get_actor_from_request(self.request))
def get_album_list2(self, request, *args, **kwargs): queryset = (music_models.Album.objects.exclude( moderation_filters.get_filtered_content_query( moderation_filters.USER_FILTER_CONFIG["ALBUM"], request.user)).with_tracks_count().order_by("artist__name")) data = request.GET or request.POST filterset = filters.AlbumList2FilterSet(data, queryset=queryset) queryset = filterset.qs actor = utils.get_actor_from_request(request) queryset = queryset.playable_by(actor) type = data.get("type", "alphabeticalByArtist") if type == "alphabeticalByArtist": queryset = queryset.order_by("artist__name") elif type == "random": queryset = queryset.order_by("?") elif type == "alphabeticalByName" or not type: queryset = queryset.order_by("artist__title") elif type == "recent" or not type: queryset = queryset.exclude( release_date__in=["", None]).order_by("-release_date") elif type == "newest" or not type: queryset = queryset.order_by("-creation_date") elif type == "byGenre" and data.get("genre"): genre = data.get("genre") queryset = queryset.filter( Q(tagged_items__tag__name=genre) | Q(artist__tagged_items__tag__name=genre)) elif type == "byYear": try: boundaries = [ int(data.get("fromYear", 0)), int(data.get("toYear", 99999999)), ] except (TypeError, ValueError): return response.Response({ "error": { "code": 10, "message": "Invalid fromYear or toYear parameter", } }) # because, yeah, the specification explicitly state that fromYear can be greater # than toYear, to indicate reverse ordering… # http://www.subsonic.org/pages/api.jsp#getAlbumList2 from_year = min(boundaries) to_year = max(boundaries) queryset = queryset.filter(release_date__year__gte=from_year, release_date__year__lte=to_year) if boundaries[0] <= boundaries[1]: queryset = queryset.order_by("release_date") else: queryset = queryset.order_by("-release_date") try: offset = int(data["offset"]) except (TypeError, KeyError, ValueError): offset = 0 try: size = int(data["size"]) except (TypeError, KeyError, ValueError): size = 50 size = min(size, 500) queryset = queryset[offset:offset + size] data = { "albumList2": { "album": serializers.get_album_list2_data(queryset) } } return response.Response(data)