Create tracks from troi recommendations (#2408)

This commit is contained in:
Petitminion 2025-03-01 00:08:10 +01:00
parent 2c0451704f
commit f270d140af
8 changed files with 39 additions and 6 deletions

View File

@ -1541,3 +1541,10 @@ Each api request to playlist tracks or radio tracks trigger the hook if tracks u
If your instance is big your ip might get rate limited. If your instance is big your ip might get rate limited.
""" """
THIRD_PARTY_UPLOAD_MAX_UPLOADS = env.int("THIRD_PARTY_UPLOAD_MAX_UPLOADS", default=10) THIRD_PARTY_UPLOAD_MAX_UPLOADS = env.int("THIRD_PARTY_UPLOAD_MAX_UPLOADS", default=10)
"""
This will enable the creation of metadata for tracks recommended by troi but missing in the db.
If you have a lot of user using the troi radios this might generate a lot of metadata.
"""
TROI_CREATE_METADATA = env.bool("TROI_CREATE_METADATA", default=True)

View File

@ -706,6 +706,15 @@ class Track(APIModelMixin):
track[0].artist_credit.set(artists_credits) track[0].artist_credit.set(artists_credits)
return track return track
@classmethod
def create_from_api(cls, **kwargs):
if kwargs.get("id"):
raw_data = cls.api.get(id=kwargs["id"], includes=cls.api_includes)
else:
raw_data = cls.api.search(**kwargs)[0]
cleaned_data = cls.clean_musicbrainz_data(raw_data)
return importers.load(cls, cleaned_data, raw_data, cls.import_hooks)
@property @property
def listen_url(self) -> str: def listen_url(self) -> str:
# Not using reverse because this is slow # Not using reverse because this is slow

View File

@ -3,11 +3,13 @@ import time
import troi import troi
import troi.core import troi.core
from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db.models import Q from django.db.models import Q
from requests.exceptions import ConnectTimeout from requests.exceptions import ConnectTimeout
from config import plugins
from funkwhale_api.music import models as music_models from funkwhale_api.music import models as music_models
from funkwhale_api.typesense import utils from funkwhale_api.typesense import utils
@ -38,6 +40,18 @@ def validate(config):
return True return True
def create_and_fetch_troi_tracks(recommended_recordings):
"""Create a track in Funkwhale database from a troi recording"""
# to do : settings.THIRD_PARTY_UPLOAD_MAX_UPLOADS
for recording in recommended_recordings:
track, created = music_models.Track.create_from_api(recording.mbid)
plugins.trigger_hook(
plugins.TRIGGER_THIRD_PARTY_UPLOAD,
track=track,
)
def build_radio_queryset(patch, radio_qs): def build_radio_queryset(patch, radio_qs):
"""Take a troi patch, match the missing mbid and then build a radio queryset""" """Take a troi patch, match the missing mbid and then build a radio queryset"""
@ -102,11 +116,13 @@ def build_radio_queryset(patch, radio_qs):
end_time_resolv = time.time() end_time_resolv = time.time()
logger.info( logger.info(
"Resolving " "Resolved "
+ str(len(recommended_recordings_not_found)) + str(len(recommended_recordings_not_found))
+ " tracks in " + " tracks in "
+ str(end_time_resolv - start_time_resolv) + str(end_time_resolv - start_time_resolv)
) )
if settings.TROI_CREATE_METADATA:
create_and_fetch_troi_tracks(recommended_recordings_not_found)
cached_match = cache.get_many(recommended_mbids) cached_match = cache.get_many(recommended_mbids)

View File

@ -1,5 +1,4 @@
import datetime import datetime
import json
import logging import logging
import random import random
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
@ -487,6 +486,6 @@ class Troi(SessionRadio):
def get_queryset(self, **kwargs): def get_queryset(self, **kwargs):
qs = super().get_queryset(**kwargs) qs = super().get_queryset(**kwargs)
config = self.append_lb_config(json.loads(kwargs["config"])) config = self.append_lb_config(kwargs["config"])
return lb_recommendations.run(config, candidates=qs) return lb_recommendations.run(config, candidates=qs)

View File

@ -1,5 +1,4 @@
import datetime import datetime
import json
import logging import logging
import pickle import pickle
import random import random
@ -521,6 +520,6 @@ class Troi(SessionRadio):
def get_queryset(self, **kwargs): def get_queryset(self, **kwargs):
qs = super().get_queryset(**kwargs) qs = super().get_queryset(**kwargs)
config = self.append_lb_config(json.loads(kwargs["config"])) config = self.append_lb_config(kwargs["config"])
return lb_recommendations.run(config, candidates=qs) return lb_recommendations.run(config, candidates=qs)

View File

@ -9,6 +9,7 @@ recording_list = [
), ),
Recording( Recording(
name="Untouchable", name="Untouchable",
mbid="87dfa566-21c3-45ed-bc42-1d345b8563fa",
artist_credit=ArtistCredit(artists=[Artist(name="Another lol")]), artist_credit=ArtistCredit(artists=[Artist(name="Another lol")]),
), ),
Recording( Recording(
@ -41,7 +42,7 @@ class DummyElement(Element):
Recording( Recording(
name="I Want It That Way", mbid="87dfa566-21c3-45ed-bc42-1d345b8563fa" name="I Want It That Way", mbid="87dfa566-21c3-45ed-bc42-1d345b8563fa"
), ),
Recording(name="Untouchable"), Recording(name="Untouchable", mbid="87dfa566-21c3-45ed-bc42-1d345b8563fa"),
Recording( Recording(
name="The Perfect Kiss", mbid="ec0da94e-fbfe-4eb0-968e-024d4c32d1d0" name="The Perfect Kiss", mbid="ec0da94e-fbfe-4eb0-968e-024d4c32d1d0"
), ),

View File

@ -34,6 +34,7 @@ def test_can_build_radio_queryset_with_fw_db(factories, mocker):
assert list( assert list(
Track.objects.all().filter(Q(mbid__in=recommended_recording_mbids)) Track.objects.all().filter(Q(mbid__in=recommended_recording_mbids))
) == list(radio_qs) ) == list(radio_qs)
assert Track.objects.filter(mbid="395bd5a1-79cc-4e04-8869-ca9eabc78d09").exists()
def test_build_radio_queryset_without_fw_db(mocker): def test_build_radio_queryset_without_fw_db(mocker):

View File

@ -0,0 +1 @@
Create tracks from troi recommendations (#2408)