fixed song process

This commit is contained in:
Alexander Karpov 2024-12-03 01:19:39 +03:00
parent b72ebe6e8c
commit 66bd074149
2 changed files with 71 additions and 27 deletions

View File

@ -8,7 +8,7 @@
except requests.exceptions.JSONDecodeError: except requests.exceptions.JSONDecodeError:
print("Failed to initialize GoogleTranslator due to external API issues.") print("Failed to initialize GoogleTranslator due to external API issues.")
from django.core.files import File from django.core.files import File
from django.db import transaction from django.db import IntegrityError, transaction
from django.utils.text import slugify from django.utils.text import slugify
from mutagen import File as MutagenFile from mutagen import File as MutagenFile
from mutagen.id3 import APIC, ID3, TCON, TORY, TextFrame from mutagen.id3 import APIC, ID3, TCON, TORY, TextFrame
@ -19,6 +19,7 @@
from akarpov.music.models import Album, Author, Song from akarpov.music.models import Album, Author, Song
from akarpov.music.services.info import generate_readable_slug, search_all_platforms from akarpov.music.services.info import generate_readable_slug, search_all_platforms
from akarpov.users.models import User from akarpov.users.models import User
from akarpov.utils.generators import generate_charset # Import generate_charset
def get_or_create_author(author_name): def get_or_create_author(author_name):
@ -26,9 +27,26 @@ def get_or_create_author(author_name):
with transaction.atomic(): with transaction.atomic():
author = Author.objects.filter(name__iexact=author_name).order_by("id").first() author = Author.objects.filter(name__iexact=author_name).order_by("id").first()
if author is None: if author is None:
author = Author.objects.create( for attempt in range(5):
name=author_name, slug=generate_readable_slug(author_name, Author) try:
slug = generate_readable_slug(author_name, Author)
author = Author.objects.create(name=author_name, slug=slug)
return author
except IntegrityError:
# Slug conflict, retry slug generation
continue
else:
# If we still fail, get the existing author
author = (
Author.objects.filter(name__iexact=author_name)
.order_by("id")
.first()
) )
if author:
return author
else:
raise Exception("Failed to create or get author")
else:
return author return author
@ -40,9 +58,24 @@ def get_or_create_album(album_name):
with transaction.atomic(): with transaction.atomic():
album = Album.objects.filter(name__iexact=album_name).order_by("id").first() album = Album.objects.filter(name__iexact=album_name).order_by("id").first()
if album is None: if album is None:
album = Album.objects.create( for attempt in range(5):
name=album_name, slug=generate_readable_slug(album_name, Album) try:
slug = generate_readable_slug(album_name, Album)
album = Album.objects.create(name=album_name, slug=slug)
return album
except IntegrityError:
# Slug conflict, retry slug generation
continue
else:
# If we still fail, get the existing album
album = (
Album.objects.filter(name__iexact=album_name).order_by("id").first()
) )
if album:
return album
else:
raise Exception("Failed to create or get album")
else:
return album return album
@ -115,13 +148,13 @@ def load_track(
kwargs["release"] if "release" in kwargs else search_info.get("release", None) kwargs["release"] if "release" in kwargs else search_info.get("release", None)
) )
if album and type(album) is str and album.startswith("['"): if album and isinstance(album, str) and album.startswith("['"):
album = album.replace("['", "").replace("']", "") album = album.replace("['", "").replace("']", "")
if album: if album:
if type(album) is str: if isinstance(album, str):
album_name = album album_name = album
elif type(album) is list: elif isinstance(album, list):
album_name = album[0] album_name = album[0]
else: else:
album_name = None album_name = None
@ -136,7 +169,7 @@ def load_track(
authors = processed_authors authors = processed_authors
if sng := Song.objects.filter( if sng := Song.objects.filter(
name=name if name else p_name, name__iexact=name if name else p_name,
authors__id__in=[x.id for x in authors], authors__id__in=[x.id for x in authors],
album=album, album=album,
): ):
@ -201,6 +234,12 @@ def load_track(
new_file_name = generated_name + ".mp3" new_file_name = generated_name + ".mp3"
# Generate unique slug for the song
song.slug = generate_readable_slug(song.name, Song)
# Try to save the song, handling potential slug conflicts
for attempt in range(5):
try:
if image_path: if image_path:
with open(path, "rb") as file, open(image_path, "rb") as image: with open(path, "rb") as file, open(image_path, "rb") as image:
song.image = File(image, name=generated_name + ".png") song.image = File(image, name=generated_name + ".png")
@ -210,6 +249,14 @@ def load_track(
with open(path, "rb") as file: with open(path, "rb") as file:
song.file = File(file, name=new_file_name) song.file = File(file, name=new_file_name)
song.save() song.save()
break # Successfully saved the song
except IntegrityError:
# Slug conflict, generate a new slug using generate_charset
song.slug = generate_readable_slug(
song.name + "_" + generate_charset(5), Song
)
else:
raise Exception("Failed to save song with unique slug after multiple attempts")
if not album.image and song.image: if not album.image and song.image:
album.image = song.image album.image = song.image
@ -218,7 +265,7 @@ def load_track(
if authors: if authors:
song.authors.set([x.id for x in authors]) song.authors.set([x.id for x in authors])
# set music meta # Set music metadata
tag = MutagenFile(song.file.path) tag = MutagenFile(song.file.path)
tag["title"] = TextFrame(encoding=3, text=[name]) tag["title"] = TextFrame(encoding=3, text=[name])
if album: if album:
@ -251,7 +298,4 @@ def load_track(
if os.path.exists(image_path): if os.path.exists(image_path):
os.remove(image_path) os.remove(image_path)
song.slug = generate_readable_slug(song.name, Song)
song.save()
return song return song

View File

@ -81,11 +81,11 @@ def generate_readable_slug(name: str, model: Model) -> str:
truncated = slug[:20].rsplit("_", 1)[0] truncated = slug[:20].rsplit("_", 1)[0]
slug = truncated if truncated else slug[:20] slug = truncated if truncated else slug[:20]
original_slug = slug original_slug = slug.lower()
# Ensure uniqueness # Ensure uniqueness
counter = 1 counter = 1
while model.objects.filter(slug=slug).exists(): while model.objects.filter(slug__iexact=slug).exists():
if len(original_slug) > 14: if len(original_slug) > 14:
truncated = original_slug[:14].rsplit("_", 1)[0] truncated = original_slug[:14].rsplit("_", 1)[0]
base_slug = truncated if truncated else original_slug[:14] base_slug = truncated if truncated else original_slug[:14]