Compare commits

...

2 Commits

Author SHA1 Message Date
dependabot[bot]
bd07474bf8
Merge d4aaa05eb3 into 51f3a6bb57 2023-12-18 00:33:48 +00:00
51f3a6bb57 updated music file processing, major info retrieving update 2023-12-18 03:33:36 +03:00
8 changed files with 1366 additions and 946 deletions

View File

@ -7,10 +7,8 @@ class MusicConfig(AppConfig):
name = "akarpov.music" name = "akarpov.music"
def ready(self): def ready(self):
try: import akarpov.music.signals # noqa F401
import akarpov.music.signals # noqa F401
except ImportError:
pass
try: try:
from akarpov.music.tasks import start_next_song from akarpov.music.tasks import start_next_song

View File

@ -0,0 +1,27 @@
# Generated by Django 4.2.8 on 2023-12-17 22:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("music", "0011_alter_playlist_private_userlistenhistory"),
]
operations = [
migrations.AddField(
model_name="album",
name="meta",
field=models.JSONField(blank=True, null=True),
),
migrations.AddField(
model_name="author",
name="albums",
field=models.ManyToManyField(related_name="authors", to="music.album"),
),
migrations.AddField(
model_name="author",
name="meta",
field=models.JSONField(blank=True, null=True),
),
]

View File

@ -10,6 +10,8 @@
class Author(BaseImageModel, ShortLinkModel): class Author(BaseImageModel, ShortLinkModel):
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
link = models.URLField(blank=True) link = models.URLField(blank=True)
meta = models.JSONField(blank=True, null=True)
albums = models.ManyToManyField("Album", related_name="authors")
def get_absolute_url(self): def get_absolute_url(self):
return reverse("music:author", kwargs={"slug": self.slug}) return reverse("music:author", kwargs={"slug": self.slug})
@ -21,6 +23,7 @@ def __str__(self):
class Album(BaseImageModel, ShortLinkModel): class Album(BaseImageModel, ShortLinkModel):
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
link = models.URLField(blank=True) link = models.URLField(blank=True)
meta = models.JSONField(blank=True, null=True)
def get_absolute_url(self): def get_absolute_url(self):
return reverse("music:album", kwargs={"slug": self.slug}) return reverse("music:album", kwargs={"slug": self.slug})

View File

@ -78,7 +78,7 @@ def load_track(
str( str(
slugify( slugify(
GoogleTranslator(source="auto", target="en").translate( GoogleTranslator(source="auto", target="en").translate(
f"{song.name} {' '.join([x.name for x in song.authors])}", f"{song.name} {' '.join([x.name for x in authors])}",
target_language="en", target_language="en",
) )
) )
@ -124,9 +124,9 @@ def load_track(
data=f.read(), data=f.read(),
) )
) )
if "release" in kwargs: if "release" in kwargs and kwargs["release"]:
tag.tags.add(TORY(text=kwargs["release"])) tag.tags.add(TORY(text=kwargs["release"]))
if "genre" in kwargs: if "genre" in kwargs and kwargs["genre"]:
tag.tags.add(TCON(text=kwargs["genre"])) tag.tags.add(TCON(text=kwargs["genre"]))
tag.save() tag.save()

View File

@ -2,8 +2,6 @@
from django.conf import settings from django.conf import settings
from spotipy.oauth2 import SpotifyClientCredentials from spotipy.oauth2 import SpotifyClientCredentials
from akarpov.music.services.yandex import search_ym
def login() -> spotipy.Spotify: def login() -> spotipy.Spotify:
if not settings.MUSIC_SPOTIFY_ID or not settings.MUSIC_SPOTIFY_SECRET: if not settings.MUSIC_SPOTIFY_ID or not settings.MUSIC_SPOTIFY_SECRET:
@ -47,15 +45,7 @@ def get_track_info(name: str) -> dict:
# try to get genre # try to get genre
sp = login() sp = login()
genres = sp.album(res["album"]["external_urls"]["spotify"])["genres"] genres = sp.album(res["album"]["external_urls"]["spotify"])["genres"]
if not genres: if genres:
ym_info = search_ym(info["artist"] + " " + info["title"])
if ym_info and "genre" in ym_info:
info["genre"] = ym_info["genre"]
else:
genres = sp.artist(res["artists"][0]["external_urls"]["spotify"])["genres"]
if genres:
info["genre"] = genres[0]
else:
info["genre"] = genres[0] info["genre"] = genres[0]
return info return info

View File

@ -2,11 +2,13 @@
from random import randint from random import randint
from django.conf import settings from django.conf import settings
from django.utils.text import slugify from django.core.files import File
from yandex_music import Client, Playlist, Search, Track from yandex_music import Client, Playlist, Search, Track
from yandex_music.exceptions import NotFoundError
from akarpov.music import tasks from akarpov.music import tasks
from akarpov.music.models import Song, SongInQue from akarpov.music.models import Album as AlbumModel
from akarpov.music.models import Author, Song, SongInQue
from akarpov.music.services.db import load_track from akarpov.music.services.db import load_track
@ -43,7 +45,7 @@ def search_ym(name: str):
return info return info
def load_file_meta(track: int, user_id: int): def load_file_meta(track: int, user_id: int) -> str:
que = SongInQue.objects.create() que = SongInQue.objects.create()
client = login() client = login()
track = client.tracks(track)[0] # type: Track track = client.tracks(track)[0] # type: Track
@ -55,19 +57,32 @@ def load_file_meta(track: int, user_id: int):
name=track.title, album__name=track.albums[0].title name=track.title, album__name=track.albums[0].title
): ):
que.delete() que.delete()
return sng.first() return str(sng.first())
except IndexError: except IndexError:
que.delete() que.delete()
return return ""
filename = slugify(f"{track.artists[0].name} - {track.title}") print("Start downloading")
filename = f"_{str(randint(10000, 9999999))}"
orig_path = f"{settings.MEDIA_ROOT}/{filename}.mp3" orig_path = f"{settings.MEDIA_ROOT}/{filename}.mp3"
album = track.albums[0] album = track.albums[0]
track.download(filename=orig_path, codec="mp3") track.download(filename=orig_path, codec="mp3")
img_pth = str(settings.MEDIA_ROOT + f"/_{str(randint(10000, 99999))}.png") img_pth = str(settings.MEDIA_ROOT + f"/_{str(randint(10000, 99999))}.png")
track.download_cover(filename=img_pth) try:
track.download_cover(filename=img_pth)
except NotFoundError:
img_pth = None
print("Downloaded file")
try:
lyrics = track.get_lyrics("LRC").fetch_lyrics()
except NotFoundError:
lyrics = ""
print("Start loading")
song = load_track( song = load_track(
orig_path, orig_path,
img_pth, img_pth,
@ -77,7 +92,11 @@ def load_file_meta(track: int, user_id: int):
track.title, track.title,
release=album.release_date, release=album.release_date,
genre=album.genre, genre=album.genre,
lyrics=lyrics,
explicit=track.explicit,
track_source=track.track_source,
) )
print("Loaded")
if os.path.exists(orig_path): if os.path.exists(orig_path):
os.remove(orig_path) os.remove(orig_path)
if os.path.exists(img_pth): if os.path.exists(img_pth):
@ -96,3 +115,65 @@ def load_playlist(link: str, user_id: int):
tasks.load_ym_file_meta.apply_async( tasks.load_ym_file_meta.apply_async(
kwargs={"track": track.track.id, "user_id": user_id} kwargs={"track": track.track.id, "user_id": user_id}
) )
def update_album_info(album: AlbumModel) -> None:
client = login()
search = client.search(album.name, type_="album") # type: Search
if search.albums:
search_album = search.albums.results[0]
data = {
"name": search_album.title,
"tracks": search_album.track_count,
"explicit": search_album.explicit,
"year": search_album.year,
"genre": search_album.genre,
"description": search_album.description,
"type": search_album.type,
}
authors = []
if search_album.artists:
authors = [
Author.objects.get_or_create(name=x.name)[0]
for x in search_album.artists
]
album.authors.set(authors)
album.meta = data
image_path = str(settings.MEDIA_ROOT + f"/_{str(randint(10000, 99999))}.png")
if not search_album.cover_uri:
album.save()
return
search_album.download_cover(filename=image_path)
with open(image_path, "rb") as f:
album.image = File(f, name=image_path.split("/")[-1])
album.save()
os.remove(image_path)
def update_author_info(author: Author) -> None:
client = login()
search = client.search(author.name, type_="artist") # type: Search
print("Loading author info " + author.name)
if search.artists:
search_artist = search.artists.results[0]
data = {
"name": search_artist.name,
"description": search_artist.description,
"genres": search_artist.genres,
}
author.meta = data
image_path = str(settings.MEDIA_ROOT + f"/_{str(randint(10000, 99999))}.png")
if not search_artist.cover:
author.save()
return
print("Downloading image")
search_artist.cover.download(filename=image_path)
with open(image_path, "rb") as f:
author.image = File(f, name=image_path.split("/")[-1])
author.save()
os.remove(image_path)

View File

@ -4,6 +4,7 @@
from django.dispatch import receiver from django.dispatch import receiver
from akarpov.music.models import Album, Author, PlaylistSong, Song, SongUserRating from akarpov.music.models import Album, Author, PlaylistSong, Song, SongUserRating
from akarpov.music.services.yandex import update_album_info, update_author_info
@receiver(post_delete, sender=Song) @receiver(post_delete, sender=Song)
@ -16,15 +17,13 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
@receiver(post_save, sender=Author) @receiver(post_save, sender=Author)
def author_create(sender, instance, created, **kwargs): def author_create(sender, instance, created, **kwargs):
if created: if created:
# TODO: add logic to retrieve author info here update_author_info(instance)
return
@receiver(post_save, sender=Album) @receiver(post_save, sender=Album)
def album_create(sender, instance, created, **kwargs): def album_create(sender, instance, created, **kwargs):
if created: if created:
# TODO: add logic to retrieve author info here update_album_info(instance)
return
@receiver(post_save) @receiver(post_save)

2156
poetry.lock generated

File diff suppressed because it is too large Load Diff