old playlist imports

This commit is contained in:
2024-07-23 00:59:06 +02:00
parent ea3ad0e0c4
commit 1bacafd8b2
7 changed files with 107 additions and 36 deletions
+15 -1
View File
@@ -1,4 +1,6 @@
from django.contrib import admin from django.contrib import admin
from django.utils.http import urlencode
from django.shortcuts import redirect
from .models import Track, Artist, Album, Background, Vote, Profile from .models import Track, Artist, Album, Background, Vote, Profile
class TrackAdmin(admin.ModelAdmin): class TrackAdmin(admin.ModelAdmin):
@@ -13,8 +15,20 @@ class VoteAdmin(admin.ModelAdmin):
pass pass
class ProfileAdmin(admin.ModelAdmin): class ProfileAdmin(admin.ModelAdmin):
pass pass
class AllTrackAdmin(admin.ModelAdmin):
list_display = ["name", "artist", "old", "from_playlist"]
list_filter = ["old", "from_playlist"]
def get_queryset(self, request):
return (Track.all_tracks.all())
def changelist_view(self, request, extra_context=None):
if 'old__exact' not in request.GET:
default_filter = urlencode({'old__exact': '0'}) # 'True' or 'False'
return redirect(f"{request.path}?{default_filter}")
return super().changelist_view(request, extra_context=extra_context)
admin.site.register(Track, TrackAdmin)
#admin.site.register(Track, TrackAdmin)
admin.site.register(Track, AllTrackAdmin)
admin.site.register(Artist, ArtistAdmin) admin.site.register(Artist, ArtistAdmin)
admin.site.register(Album, AlbumAdmin) admin.site.register(Album, AlbumAdmin)
admin.site.register(Background, BackgroundAdmin) admin.site.register(Background, BackgroundAdmin)
+6 -5
View File
@@ -45,19 +45,20 @@ class Track(models.Model):
id = models.CharField(primary_key=True, max_length=128) id = models.CharField(primary_key=True, max_length=128)
nominated_by = models.ForeignKey(User, null=True, default=None, on_delete=models.SET_NULL) nominated_by = models.ForeignKey(User, blank=True, null=True, default=None, on_delete=models.SET_NULL)
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
artists = models.ManyToManyField(Artist) artists = models.ManyToManyField(Artist)
album = models.ForeignKey(Album, null=True, on_delete=models.SET_NULL) album = models.ForeignKey(Album, blank=True, null=True, on_delete=models.SET_NULL)
explicit = models.BooleanField(default=False) explicit = models.BooleanField(default=False)
duration_ms = models.PositiveIntegerField(null=True) duration_ms = models.PositiveIntegerField(blank=True, null=True)
popularity = models.PositiveIntegerField(null=True) popularity = models.PositiveIntegerField(blank=True, null=True)
banter = models.TextField(blank=True) banter = models.TextField(null=True, blank=True)
banter_done = models.BooleanField(default=False) banter_done = models.BooleanField(default=False)
old = models.BooleanField(default=False) old = models.BooleanField(default=False)
from_playlist = models.CharField(max_length=255, null=True, blank=True, default=None)
objects = TrackManager() objects = TrackManager()
all_tracks = models.Manager() all_tracks = models.Manager()
+11
View File
@@ -91,4 +91,15 @@ class Spotify():
r.raise_for_status() r.raise_for_status()
return r.json() return r.json()
def get_playlist_info(self, playlist_id):
token = self.get_system_token()
url = 'https://api.spotify.com/v1/playlists/' + playlist_id
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
}
r = requests.get(url, headers=headers)
r.raise_for_status()
return r.json()
spt = Spotify() spt = Spotify()
+7
View File
@@ -13,6 +13,13 @@ Instellingen
<input type="submit" value="" class="icon admin-panel" /> <input type="submit" value="" class="icon admin-panel" />
</div> </div>
</form> </form>
<form action="{% url 'playlist-import' %}" method="post">
{% csrf_token %}
<p>Geef een playlist url om oude nummers te importeren:</p>
<input type="text" id="spotify-input" name="playlist_link" placeholder="Spotify-link">
<input type="submit" value="Importeer">
</form>
{% comment %} {% if sptDisplayName %} {% comment %} {% if sptDisplayName %}
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
+1
View File
@@ -9,6 +9,7 @@ urlpatterns = [
path('vote/undo', views.UndoView.as_view(), name="undo"), path('vote/undo', views.UndoView.as_view(), name="undo"),
path('vote/skip', views.SkipView.as_view(), name="skip"), path('vote/skip', views.SkipView.as_view(), name="skip"),
path('settings/', views.SettingsView.as_view(), name="settings"), path('settings/', views.SettingsView.as_view(), name="settings"),
path('settings/playlist-import', views.PlaylistImportView.as_view(), name="playlist-import"),
path('overview/', views.OverView.as_view(), name="overview"), path('overview/', views.OverView.as_view(), name="overview"),
path('overview/playlist', views.PlaylistListView.as_view(), name="playlist-list"), path('overview/playlist', views.PlaylistListView.as_view(), name="playlist-list"),
path('overview/playlist/<int:id>', views.PlaylistDetailView.as_view(), name="playlist-detail"), path('overview/playlist/<int:id>', views.PlaylistDetailView.as_view(), name="playlist-detail"),
+31 -1
View File
@@ -1,4 +1,4 @@
from .models import Track, Vote from .models import Track, Vote, Album, Artist
from random import choice, seed from random import choice, seed
def from_json(cls, json): def from_json(cls, json):
@@ -25,3 +25,33 @@ def get_unvoted(user):
return (Track.objects.get(pk=random_track), skipped) return (Track.objects.get(pk=random_track), skipped)
except IndexError: except IndexError:
return (None, False) return (None, False)
def track_from_json(json):
"""Creates the track, album and artist from spotify response."""
# Album artists
album_artists = []
for artist in json["album"]["artists"]:
album_artists.append(from_json(Artist, artist))
del json["album"]["artists"]
# Album
album = 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(from_json(Artist, artist))
del json["artists"]
# Track
track = from_json(Track, json)
for artist in track_artists:
track.artists.add(artist)
track.album = album
track.save()
return track
+36 -29
View File
@@ -11,7 +11,7 @@ from datetime import UTC, datetime
from collections import OrderedDict from collections import OrderedDict
from dotenv import load_dotenv from dotenv import load_dotenv
from .models import Track, Artist, Album, Vote, Background, Profile, Playlist from .models import Track, Artist, Album, Vote, Background, Profile, Playlist
from .utils import from_json, get_unvoted from .utils import track_from_json, get_unvoted
from .spotify import spt from .spotify import spt
from .tasks import get_banter, get_and_dither_image from .tasks import get_banter, get_and_dither_image
@@ -28,6 +28,8 @@ class VoteView(LoginRequiredMixin, View):
def get(self, request, undo=None): def get(self, request, undo=None):
(track, skipped) = get_unvoted(request.user) (track, skipped) = get_unvoted(request.user)
if track and not track.album.image: if track and not track.album.image:
if not track.album.image_url:
get_and_dither_image("https://picsum.photos/256", track.album, "image")
get_and_dither_image(track.album.image_url, track.album, "image") get_and_dither_image(track.album.image_url, track.album, "image")
return TemplateResponse(request, "Vote.html", {"track": track, "undo": undo, "skipped": skipped}) return TemplateResponse(request, "Vote.html", {"track": track, "undo": undo, "skipped": skipped})
def post(self, request): def post(self, request):
@@ -86,7 +88,7 @@ class NominateView(LoginRequiredMixin, View):
get_banter.delay(track.id) get_banter.delay(track.id)
return TemplateResponse(request, "Nominate.html", { return TemplateResponse(request, "Nominate.html", {
"message_type": "warning", "message_type": "warning",
"message": "Hey een klassieker.", "message": f"Hey een klassieker, die stond al in {track.from_playlist}. Geen probleem, we proberen hem nog een keer dit jaar!",
"message_title": str(track) "message_title": str(track)
}) })
return TemplateResponse(request, "Nominate.html", { return TemplateResponse(request, "Nominate.html", {
@@ -101,31 +103,8 @@ class NominateView(LoginRequiredMixin, View):
print(e) print(e)
return TemplateResponse(request, "Nominate.html", {"message_type": "error", "message": "Fout bij het ophalen van het liedje."}) return TemplateResponse(request, "Nominate.html", {"message_type": "error", "message": "Fout bij het ophalen van het liedje."})
# Album artists track = track_from_json(json)
album_artists = []
for artist in json["album"]["artists"]:
album_artists.append(from_json(Artist, artist))
del json["album"]["artists"]
# Album
album = 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(from_json(Artist, artist))
del json["artists"]
# Track
track = from_json(Track, json)
track.nominated_by = request.user track.nominated_by = request.user
for artist in track_artists:
track.artists.add(artist)
track.save() track.save()
dup = track.is_duplicate_of() dup = track.is_duplicate_of()
if dup: if dup:
@@ -135,8 +114,6 @@ class NominateView(LoginRequiredMixin, View):
"message": "Die hadden we al knul.", "message": "Die hadden we al knul.",
"message_title": str(dup) "message_title": str(dup)
}) })
track.album = album
track.save()
get_banter.delay(track.id) get_banter.delay(track.id)
profile.quota -= 1 profile.quota -= 1
profile.save() profile.save()
@@ -246,7 +223,6 @@ class PlaylistListView(LoginRequiredMixin, View):
return TemplateResponse(request, "PlaylistList.html") return TemplateResponse(request, "PlaylistList.html")
return self.get(request, count=count) return self.get(request, count=count)
class PlaylistDetailView(LoginRequiredMixin, View): class PlaylistDetailView(LoginRequiredMixin, View):
def get(self, request, count=None): def get(self, request, count=None):
context = {} context = {}
@@ -281,3 +257,34 @@ class SpotifyCallbackView(LoginRequiredMixin, View):
else: else:
url = spt.get_oauth_redirect() url = spt.get_oauth_redirect()
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
class PlaylistImportView(LoginRequiredMixin, View):
def get(self, request):
return HttpResponseRedirect('/settings/')
def post(self, request):
print("...")
playlist_link = self.request.POST['playlist_link']
m = re.match(r"^https:\/\/open.spotify.com\/playlist\/([a-zA-Z0-9]+)\??", playlist_link)
playlist_id = m.group(1)
print(playlist_id)
json = spt.get_playlist_info(playlist_id)
tracks = json["tracks"]["items"]
playlist_name = json["name"]
for track in tracks:
track_id = track["track"]["id"]
try:
json = spt.get_song_info(track_id)
track = track_from_json(json)
dup = track.is_duplicate_of()
if dup:
print(f"{track} hadden we al")
track.delete()
else:
track.old = True
track.from_playlist = playlist_name
track.save()
except Exception as e:
print(e)
return self.get(request)