mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2024-11-28 06:53:43 +03:00
Compare commits
10 Commits
9f18605069
...
bbe08d0f43
Author | SHA1 | Date | |
---|---|---|---|
|
bbe08d0f43 | ||
f2f5446c18 | |||
|
f39e49ab39 | ||
|
0f465e40de | ||
8f19d51410 | |||
07640962fa | |||
fbddd3c1dc | |||
79e865bf37 | |||
75d787f460 | |||
51f3a6bb57 |
|
@ -13,6 +13,11 @@
|
|||
from ..documents import FileDocument
|
||||
from .lema import lemmatize_and_remove_stopwords
|
||||
|
||||
"""
|
||||
Calculus on types of searches:
|
||||
https://new.akarpov.ru/files/FZUTFBIyfbdlDHVzxUNU
|
||||
"""
|
||||
|
||||
|
||||
class BaseSearch:
|
||||
def __init__(self, queryset: QuerySet | None = None):
|
||||
|
|
|
@ -92,9 +92,7 @@ def get_queryset(self):
|
|||
):
|
||||
return self.filter(BaseFileItem.objects.none())
|
||||
return self.filter(
|
||||
BaseFileItem.objects.cache().filter(
|
||||
user=self.request.user, parent__isnull=True
|
||||
)
|
||||
BaseFileItem.objects.filter(user=self.request.user, parent__isnull=True)
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -7,10 +7,8 @@ class MusicConfig(AppConfig):
|
|||
name = "akarpov.music"
|
||||
|
||||
def ready(self):
|
||||
try:
|
||||
import akarpov.music.signals # noqa F401
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
from akarpov.music.tasks import start_next_song
|
||||
|
||||
|
|
|
@ -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),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,31 @@
|
|||
# Generated by Django 4.2.8 on 2023-12-18 11:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("music", "0012_album_meta_author_albums_author_meta"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="author",
|
||||
name="albums",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="album",
|
||||
name="authors",
|
||||
field=models.ManyToManyField(related_name="albums", to="music.album"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="album",
|
||||
name="name",
|
||||
field=models.CharField(max_length=200, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="author",
|
||||
name="name",
|
||||
field=models.CharField(max_length=200, unique=True),
|
||||
),
|
||||
]
|
17
akarpov/music/migrations/0014_alter_album_authors.py
Normal file
17
akarpov/music/migrations/0014_alter_album_authors.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 4.2.8 on 2023-12-18 14:30
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("music", "0013_remove_author_albums_album_authors_alter_album_name_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="album",
|
||||
name="authors",
|
||||
field=models.ManyToManyField(related_name="albums", to="music.author"),
|
||||
),
|
||||
]
|
|
@ -8,8 +8,9 @@
|
|||
|
||||
|
||||
class Author(BaseImageModel, ShortLinkModel):
|
||||
name = models.CharField(max_length=200)
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
link = models.URLField(blank=True)
|
||||
meta = models.JSONField(blank=True, null=True)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("music:author", kwargs={"slug": self.slug})
|
||||
|
@ -19,8 +20,10 @@ def __str__(self):
|
|||
|
||||
|
||||
class Album(BaseImageModel, ShortLinkModel):
|
||||
name = models.CharField(max_length=200)
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
link = models.URLField(blank=True)
|
||||
meta = models.JSONField(blank=True, null=True)
|
||||
authors = models.ManyToManyField("Author", related_name="albums")
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("music:album", kwargs={"slug": self.slug})
|
||||
|
|
|
@ -27,16 +27,28 @@ def load_track(
|
|||
if album and type(album) is str and album.startswith("['"):
|
||||
album = album.replace("['", "").replace("']", "")
|
||||
|
||||
re_authors = []
|
||||
if authors:
|
||||
authors = [Author.objects.get_or_create(name=x)[0] for x in authors if authors]
|
||||
else:
|
||||
authors = []
|
||||
for x in authors:
|
||||
try:
|
||||
re_authors.append(Author.objects.get(name=x))
|
||||
except Author.DoesNotExist:
|
||||
re_authors.append(Author.objects.create(name=x))
|
||||
authors = re_authors
|
||||
album_name = None
|
||||
if album:
|
||||
if type(album) is str:
|
||||
album = Album.objects.get_or_create(name=album)[0]
|
||||
album_name = album
|
||||
elif type(album) is list:
|
||||
album = Album.objects.get_or_create(name=album[0])[0]
|
||||
album_name = album[0]
|
||||
else:
|
||||
album_name = None
|
||||
if album_name:
|
||||
try:
|
||||
album = Album.objects.get(name=album_name)
|
||||
except Album.DoesNotExist:
|
||||
album = Album.objects.create(name=album_name)
|
||||
if not album_name:
|
||||
album = None
|
||||
|
||||
if sng := Song.objects.filter(
|
||||
|
@ -78,7 +90,7 @@ def load_track(
|
|||
str(
|
||||
slugify(
|
||||
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",
|
||||
)
|
||||
)
|
||||
|
@ -101,7 +113,7 @@ def load_track(
|
|||
album.save()
|
||||
|
||||
if authors:
|
||||
song.authors.set(authors)
|
||||
song.authors.set([x.id for x in authors])
|
||||
|
||||
# set music meta
|
||||
tag = MutagenFile(song.file.path)
|
||||
|
@ -124,9 +136,9 @@ def load_track(
|
|||
data=f.read(),
|
||||
)
|
||||
)
|
||||
if "release" in kwargs:
|
||||
if "release" in kwargs and 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.save()
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
from django.conf import settings
|
||||
from spotipy.oauth2 import SpotifyClientCredentials
|
||||
|
||||
from akarpov.music.services.yandex import search_ym
|
||||
|
||||
|
||||
def login() -> spotipy.Spotify:
|
||||
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
|
||||
sp = login()
|
||||
genres = sp.album(res["album"]["external_urls"]["spotify"])["genres"]
|
||||
if not 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]
|
||||
|
||||
return info
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
from random import randint
|
||||
|
||||
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.exceptions import NotFoundError
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -43,7 +45,7 @@ def search_ym(name: str):
|
|||
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()
|
||||
client = login()
|
||||
track = client.tracks(track)[0] # type: Track
|
||||
|
@ -55,19 +57,27 @@ def load_file_meta(track: int, user_id: int):
|
|||
name=track.title, album__name=track.albums[0].title
|
||||
):
|
||||
que.delete()
|
||||
return sng.first()
|
||||
return str(sng.first())
|
||||
except IndexError:
|
||||
que.delete()
|
||||
return
|
||||
return ""
|
||||
|
||||
filename = slugify(f"{track.artists[0].name} - {track.title}")
|
||||
filename = f"_{str(randint(10000, 9999999))}"
|
||||
orig_path = f"{settings.MEDIA_ROOT}/{filename}.mp3"
|
||||
album = track.albums[0]
|
||||
|
||||
track.download(filename=orig_path, codec="mp3")
|
||||
img_pth = str(settings.MEDIA_ROOT + f"/_{str(randint(10000, 99999))}.png")
|
||||
|
||||
try:
|
||||
track.download_cover(filename=img_pth)
|
||||
except NotFoundError:
|
||||
img_pth = None
|
||||
|
||||
try:
|
||||
lyrics = track.get_lyrics("LRC").fetch_lyrics()
|
||||
except NotFoundError:
|
||||
lyrics = ""
|
||||
song = load_track(
|
||||
orig_path,
|
||||
img_pth,
|
||||
|
@ -77,6 +87,9 @@ def load_file_meta(track: int, user_id: int):
|
|||
track.title,
|
||||
release=album.release_date,
|
||||
genre=album.genre,
|
||||
lyrics=lyrics,
|
||||
explicit=track.explicit,
|
||||
track_source=track.track_source,
|
||||
)
|
||||
if os.path.exists(orig_path):
|
||||
os.remove(orig_path)
|
||||
|
@ -96,3 +109,64 @@ def load_playlist(link: str, user_id: int):
|
|||
tasks.load_ym_file_meta.apply_async(
|
||||
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,
|
||||
}
|
||||
|
||||
album.meta = data
|
||||
image_path = str(settings.MEDIA_ROOT + f"/_{str(randint(10000, 99999))}.png")
|
||||
if search_album.cover_uri:
|
||||
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)
|
||||
|
||||
authors = []
|
||||
if search_album.artists:
|
||||
for x in search_album.artists:
|
||||
try:
|
||||
authors.append(Author.objects.get(name=x.name))
|
||||
except Author.DoesNotExist:
|
||||
authors.append(Author.objects.create(name=x.name))
|
||||
album.authors.set([x.id for x in authors])
|
||||
album.save()
|
||||
|
||||
|
||||
def update_author_info(author: Author) -> None:
|
||||
client = login()
|
||||
search = client.search(author.name, type_="artist") # type: Search
|
||||
|
||||
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
|
||||
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)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
from django.dispatch import receiver
|
||||
|
||||
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)
|
||||
|
@ -16,15 +17,13 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
|
|||
@receiver(post_save, sender=Author)
|
||||
def author_create(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
# TODO: add logic to retrieve author info here
|
||||
return
|
||||
update_author_info(instance)
|
||||
|
||||
|
||||
@receiver(post_save, sender=Album)
|
||||
def album_create(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
# TODO: add logic to retrieve author info here
|
||||
return
|
||||
update_album_info(instance)
|
||||
|
||||
|
||||
@receiver(post_save)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
set -o errexit
|
||||
set -o nounset
|
||||
|
||||
python manage.py makemigrations
|
||||
python manage.py migrate
|
||||
rm -f './celerybeat.pid'
|
||||
celery -A config.celery_app beat -l INFO
|
||||
|
|
1929
poetry.lock
generated
1929
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
|
@ -28,12 +28,12 @@ django-crispy-forms = "^2.1"
|
|||
crispy-bootstrap5 = "^0.7"
|
||||
django-redis = "^5.2.0"
|
||||
django-ckeditor = "^6.5.1"
|
||||
django-colorfield = "^0.8.0"
|
||||
django-colorfield = "^0.11.0"
|
||||
djangorestframework = "^3.14.0"
|
||||
django-rest-auth = "^0.9.5"
|
||||
django-cors-headers = "^4.0.0"
|
||||
drf-spectacular = "^0.26.2"
|
||||
werkzeug = {extras = ["watchdog"], version = "^2.3.4"}
|
||||
werkzeug = {extras = ["watchdog"], version = "^3.0.1"}
|
||||
ipdb = "^0.13.13"
|
||||
watchfiles = "^0.18.1"
|
||||
mypy = "^0.991"
|
||||
|
@ -77,7 +77,7 @@ pydub = "^0.25.1"
|
|||
python-mpd2 = "^3.0.5"
|
||||
yandex-music = "^2.1.1"
|
||||
pyjwt = "^2.8.0"
|
||||
rawpy = "^0.18.1"
|
||||
rawpy = "^0.19.0"
|
||||
xvfbwrapper = "^0.2.9"
|
||||
vtk = "^9.2.6"
|
||||
ffmpeg-python = "^0.2.0"
|
||||
|
|
Loading…
Reference in New Issue
Block a user