mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2025-09-14 04:12:27 +03:00
updated song liked
This commit is contained in:
parent
03c05d7adf
commit
e394705eca
|
@ -279,39 +279,33 @@ def validate(self, attrs):
|
|||
|
||||
def create(self, validated_data):
|
||||
song = Song.objects.get(slug=validated_data["song"])
|
||||
if self.context["like"]:
|
||||
if SongUserRating.objects.filter(
|
||||
song=song, user=self.context["request"].user
|
||||
).exists():
|
||||
song_user_rating = SongUserRating.objects.get(
|
||||
song=song, user=self.context["request"].user
|
||||
)
|
||||
if song_user_rating.like:
|
||||
song_user_rating.delete()
|
||||
user = self.context["request"].user
|
||||
is_like_action = self.context["like"]
|
||||
|
||||
try:
|
||||
existing_rating = SongUserRating.objects.get(song=song, user=user)
|
||||
|
||||
if is_like_action:
|
||||
if existing_rating.like:
|
||||
existing_rating.delete()
|
||||
return None
|
||||
else:
|
||||
song_user_rating.like = True
|
||||
song_user_rating.save()
|
||||
existing_rating.like = True
|
||||
existing_rating.save()
|
||||
return existing_rating
|
||||
else:
|
||||
song_user_rating = SongUserRating.objects.create(
|
||||
song=song, user=self.context["request"].user, like=True
|
||||
)
|
||||
else:
|
||||
if SongUserRating.objects.filter(
|
||||
song=song, user=self.context["request"].user
|
||||
).exists():
|
||||
song_user_rating = SongUserRating.objects.get(
|
||||
song=song, user=self.context["request"].user
|
||||
)
|
||||
if not song_user_rating.like:
|
||||
song_user_rating.delete()
|
||||
if not existing_rating.like:
|
||||
existing_rating.delete()
|
||||
return None
|
||||
else:
|
||||
song_user_rating.like = False
|
||||
song_user_rating.save()
|
||||
else:
|
||||
song_user_rating = SongUserRating.objects.create(
|
||||
song=song, user=self.context["request"].user, like=False
|
||||
)
|
||||
return song_user_rating
|
||||
existing_rating.like = False
|
||||
existing_rating.save()
|
||||
return existing_rating
|
||||
|
||||
except SongUserRating.DoesNotExist:
|
||||
return SongUserRating.objects.create(
|
||||
song=song, user=user, like=is_like_action
|
||||
)
|
||||
|
||||
|
||||
class ListSongSlugsSerializer(serializers.Serializer):
|
||||
|
|
|
@ -323,7 +323,7 @@ def get_serializer_context(self, **kwargs):
|
|||
return context
|
||||
|
||||
|
||||
class LikeSongAPIView(generics.CreateAPIView):
|
||||
class LikeSongAPIView(generics.GenericAPIView):
|
||||
serializer_class = LikeDislikeSongSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
|
@ -335,8 +335,19 @@ def get_serializer_context(self, **kwargs):
|
|||
context["like"] = True
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
class DislikeSongAPIView(generics.CreateAPIView):
|
||||
result = serializer.save()
|
||||
|
||||
if result is None:
|
||||
return Response({"message": "Like removed"}, status=200)
|
||||
else:
|
||||
return Response({"message": "Song liked", "liked": result.like}, status=201)
|
||||
|
||||
|
||||
class DislikeSongAPIView(generics.GenericAPIView):
|
||||
serializer_class = LikeDislikeSongSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
|
@ -348,6 +359,19 @@ def get_serializer_context(self, **kwargs):
|
|||
context["like"] = False
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
result = serializer.save()
|
||||
|
||||
if result is None:
|
||||
return Response({"message": "Dislike removed"}, status=200)
|
||||
else:
|
||||
return Response(
|
||||
{"message": "Song disliked", "liked": result.like}, status=201
|
||||
)
|
||||
|
||||
|
||||
class ListAlbumsAPIView(generics.ListAPIView):
|
||||
serializer_class = ListAlbumSerializer
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import re
|
||||
import time
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
|
@ -9,7 +10,6 @@
|
|||
import numpy as np
|
||||
from django.core.files import File
|
||||
from django.db import IntegrityError, transaction
|
||||
from django.db.models import Count
|
||||
from django.utils.text import slugify
|
||||
from mutagen.id3 import ID3
|
||||
from mutagen.mp3 import MP3
|
||||
|
@ -259,39 +259,6 @@ def clean_title_for_slug(title: str) -> str:
|
|||
return cleaned.strip()
|
||||
|
||||
|
||||
def process_authors_string(authors_str: str) -> list[str]:
|
||||
"""Split author string into individual author names."""
|
||||
if not authors_str:
|
||||
return []
|
||||
|
||||
# First split by major separators
|
||||
authors = []
|
||||
for part in authors_str.split("/"):
|
||||
for subpart in part.split("&"):
|
||||
# Handle various featuring cases
|
||||
for feat_marker in [
|
||||
" feat.",
|
||||
" ft.",
|
||||
" featuring.",
|
||||
" presents ",
|
||||
" pres. ",
|
||||
]:
|
||||
if feat_marker in subpart.lower():
|
||||
parts = subpart.lower().split(feat_marker, 1)
|
||||
authors.extend(part.strip() for part in parts)
|
||||
break
|
||||
else:
|
||||
# Handle collaboration markers
|
||||
if " x " in subpart:
|
||||
authors.extend(p.strip() for p in subpart.split(" x "))
|
||||
else:
|
||||
authors.append(subpart.strip())
|
||||
|
||||
# Remove duplicates while preserving order
|
||||
seen = set()
|
||||
return [x for x in authors if not (x.lower() in seen or seen.add(x.lower()))]
|
||||
|
||||
|
||||
def extract_mp3_metadata(file_path: str) -> dict | None:
|
||||
"""Extract metadata from MP3 file."""
|
||||
try:
|
||||
|
@ -442,20 +409,64 @@ def get_or_create_album(album_name: str, authors: list[Author]) -> Album | None:
|
|||
raise
|
||||
|
||||
|
||||
def process_authors_string(authors_str: str) -> list[str]:
|
||||
"""Split author string into individual author names."""
|
||||
if not authors_str:
|
||||
return []
|
||||
|
||||
# First split by major delimiters
|
||||
authors = []
|
||||
|
||||
# Split by common delimiters while preserving Asian character sequences
|
||||
for part in re.split(r"[,&/](?![^\[]*\])", authors_str):
|
||||
# Clean up each part
|
||||
cleaned = part.strip()
|
||||
|
||||
# Handle featuring cases
|
||||
featuring_markers = [" feat.", " ft.", " featuring", " presents ", " pres. "]
|
||||
for marker in featuring_markers:
|
||||
if marker in cleaned.lower():
|
||||
main_artist, feat_artist = cleaned.lower().split(marker, 1)
|
||||
authors.extend(
|
||||
[a.strip() for a in [main_artist, feat_artist] if a.strip()]
|
||||
)
|
||||
break
|
||||
else:
|
||||
# Handle collaborations with 'x' or 'X'
|
||||
if " x " in cleaned or " X " in cleaned:
|
||||
collab_parts = re.split(" [xX] ", cleaned)
|
||||
authors.extend(p.strip() for p in collab_parts if p.strip())
|
||||
else:
|
||||
if cleaned:
|
||||
authors.append(cleaned)
|
||||
|
||||
# Remove duplicates while preserving order
|
||||
seen = set()
|
||||
return [x for x in authors if not (x.lower() in seen or seen.add(x.lower()))]
|
||||
|
||||
|
||||
def check_song_exists(title: str, album: Album | None, authors: list[Author]) -> bool:
|
||||
"""Check if a song already exists with the given title, album and authors."""
|
||||
if not title:
|
||||
return False
|
||||
|
||||
# Start with base query
|
||||
query = Song.objects.filter(name__iexact=title)
|
||||
|
||||
if album:
|
||||
query = query.filter(album=album)
|
||||
|
||||
if authors:
|
||||
# Ensure exact author match
|
||||
query = query.annotate(author_count=Count("authors")).filter(
|
||||
author_count=len(authors), authors__in=authors
|
||||
)
|
||||
# Get all author IDs
|
||||
author_ids = {author.id for author in authors}
|
||||
|
||||
return query.exists()
|
||||
# Filter songs that have exactly these authors
|
||||
for song in query:
|
||||
song_author_ids = set(song.authors.values_list("id", flat=True))
|
||||
if song_author_ids == author_ids:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def load_mp3_directory(
|
||||
|
@ -507,10 +518,10 @@ def load_mp3_directory(
|
|||
failed_files.append(str(mp3_path))
|
||||
continue
|
||||
|
||||
# Check for existing song
|
||||
# Check for existing song with exact matches
|
||||
if check_song_exists(metadata["title"], album, authors):
|
||||
print(
|
||||
f"Skipping existing song: {metadata['artists']} - {metadata['title']}"
|
||||
f"Skipping existing song: {' & '.join(author_names)} - {metadata['title']}"
|
||||
)
|
||||
continue
|
||||
|
||||
|
@ -526,13 +537,17 @@ def load_mp3_directory(
|
|||
f"{album.slug}.png", File(img_file), save=True
|
||||
)
|
||||
|
||||
# Create song with proper slug from file name
|
||||
file_name = os.path.splitext(os.path.basename(str(mp3_path)))[0]
|
||||
# Create song with proper slug
|
||||
_name = (
|
||||
metadata["title"]
|
||||
if metadata["title"]
|
||||
else os.path.splitext(os.path.basename(str(mp3_path)))[0]
|
||||
)
|
||||
song = Song(
|
||||
name=metadata["title"],
|
||||
length=metadata["length"],
|
||||
album=album,
|
||||
slug=generate_unique_slug(file_name, Song),
|
||||
slug=generate_unique_slug(_name, Song),
|
||||
creator=User.objects.get(id=user_id) if user_id else None,
|
||||
meta={
|
||||
"genre": metadata["genre"],
|
||||
|
@ -560,7 +575,7 @@ def load_mp3_directory(
|
|||
print(f"Error processing {mp3_path}: {str(e)}")
|
||||
failed_files.append(str(mp3_path))
|
||||
|
||||
# Trigger image cropping for all created/updated objects
|
||||
# Process image cropping for all created/updated objects
|
||||
print("Processing image cropping...")
|
||||
|
||||
for author_id in created_authors:
|
||||
|
|
Loading…
Reference in New Issue
Block a user