from django.db import models from django.contrib.auth.models import User from random import choice from .album import Album from .artist import Artist from .vote import Vote from playlist.spotify import spt #from playlist.utils import track_from_json import re class TrackManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(old=False) def from_json(self, cls, json): try: return cls.objects.get(pk=json["id"]) except cls.DoesNotExist: keys = [f.name for f in cls._meta.get_fields()] subset = {key:json[key] for key in set(keys) & set(json.keys())} return cls.objects.create(**subset) def track_from_json(self, json): """Creates the track, album and artist from spotify response.""" # Album artists album_artists = [] for artist in json["album"]["artists"]: album_artists.append(self.from_json(Artist, artist)) del json["album"]["artists"] # Album album = self.from_json(Album, json["album"]) album.image_url = json["album"]["images"][0]["url"] album.save() del json["album"] for artist in album_artists: album.artists.add(artist) # Track artists track_artists = [] for artist in json["artists"]: track_artists.append(self.from_json(Artist, artist)) del json["artists"] # Track track = self.from_json(Track, json) for artist in track_artists: track.artists.add(artist) track.album = album track.save() return track def create_from_spotify(self, spotify_link, profile): if re.match(r"^https:\/\/spotify.link.*", spotify_link): spotify_link = spt.unshort(spotify_link) m = re.match(r"^https:\/\/open.spotify.com\/track\/([a-zA-Z0-9]+)\??", spotify_link) if m is None: return None, Exception("Invalid Spotify track URL") spotify_id = m.group(1) try: existing_track = self.model.all_tracks.get(pk=spotify_id) if existing_track.old: existing_track.old = False existing_track.user = profile.user existing_track.save() return (existing_track, "Updated old track") else: return (None, "Track already exists") except: pass try: json = spt.get_song_info(spotify_id) except Exception as e: print(e) return (None, "Error fetching track") #return TemplateResponse(request, "Nominate.html", {"message_type": "error", "message": "Fout bij het ophalen van het liedje."}) track = self.track_from_json(json) track.nominated_by = profile.user track.save() dup = track.is_duplicate_of() if dup: track.delete() return (None, "Track already exists") #get_banter.delay(track.id) profile.quota -= 1 profile.save() return (track, None) class Track(models.Model): def __str__(self): s = f"'{self.name}'" if self.artists.count() > 0: artists = list(map(lambda a:a.name, self.artists.all())) s += " door " s += " & ".join(artists) return s @property def artist(self): if self.artists.count() > 0: artists = list(map(lambda a:a.name, self.artists.all())) return " & ".join(artists) @property def album_cover(self): if self.album: return self.album.image_url @property def name_sanitized(self): return re.match("[^\-\(]*\w", self.name)[0] @property def link(self): return f'https://open.spotify.com/track/{self.id}' @property def score(self): return Vote.objects.filter(track=self.id).aggregate(rating=models.Avg("points"))["rating"] def is_duplicate_of(self): tracks = Track.objects.exclude(id=self.id).filter(name__startswith=self.name_sanitized) artists = [artist.name for artist in self.artists.all()] for artist in artists: tracks = tracks.filter(artists__name__exact=artist) return tracks.first() id = models.CharField(primary_key=True, max_length=128) nominated_by = models.ForeignKey(User, blank=True, null=True, default=None, on_delete=models.SET_NULL) name = models.CharField(max_length=255) artists = models.ManyToManyField(Artist) album = models.ForeignKey(Album, blank=True, null=True, on_delete=models.SET_NULL) explicit = models.BooleanField(default=False) duration_ms = models.PositiveIntegerField(blank=True, null=True) popularity = models.PositiveIntegerField(blank=True, null=True) banter = models.TextField(null=True, blank=True) banter_done = models.BooleanField(default=False) old = models.BooleanField(default=False) from_playlist = models.CharField(max_length=255, null=True, blank=True, default=None) objects = TrackManager() all_tracks = models.Manager()