Spotify user api integration
En een begin aan een playlist maker. Doet op het moment niet veel.
This commit is contained in:
@@ -14,6 +14,7 @@ DEBUG = True
|
|||||||
|
|
||||||
ALLOWED_HOSTS = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
|
|
||||||
|
CURRENT_HOST = 'http://127.0.0.1:8000' # Needs to be set for spotify callback to work.
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'playlist.apps.PlaylistConfig',
|
'playlist.apps.PlaylistConfig',
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ from .artist import Artist
|
|||||||
from .album import Album
|
from .album import Album
|
||||||
from .vote import Vote
|
from .vote import Vote
|
||||||
from .profile import Profile, Background
|
from .profile import Profile, Background
|
||||||
|
from .playlist import Playlist
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
from django.db import models
|
||||||
|
from .track import Track
|
||||||
|
|
||||||
|
class Playlist(models.Model):
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
name = models.CharField(max_length=255)
|
||||||
|
tracks = models.ManyToManyField(Track)
|
||||||
@@ -5,6 +5,7 @@ from django.db.models.signals import post_save
|
|||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from ..spotify import spt
|
||||||
|
|
||||||
NOMINATIONS_PER_DAY = 10
|
NOMINATIONS_PER_DAY = 10
|
||||||
MAX_QUOTA = 22
|
MAX_QUOTA = 22
|
||||||
@@ -25,6 +26,10 @@ class Profile(models.Model):
|
|||||||
quota = models.FloatField(default=10.0)
|
quota = models.FloatField(default=10.0)
|
||||||
quota_last_updated = models.DateTimeField(default=timezone.now, null=False)
|
quota_last_updated = models.DateTimeField(default=timezone.now, null=False)
|
||||||
|
|
||||||
|
spt_access_token = models.CharField(max_length=128, default="", null=True)
|
||||||
|
spt_refresh_token = models.CharField(max_length=128, default="", null=True)
|
||||||
|
spt_expires = models.DateTimeField(default=None, null=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def quota_display(self):
|
def quota_display(self):
|
||||||
return int(self.quota)
|
return int(self.quota)
|
||||||
@@ -38,6 +43,53 @@ class Profile(models.Model):
|
|||||||
print(f"Er zijn {elapsed.seconds}s voorbij, je nieuwe quota is {self.quota}")
|
print(f"Er zijn {elapsed.seconds}s voorbij, je nieuwe quota is {self.quota}")
|
||||||
self.quota_last_updated = timezone.now()
|
self.quota_last_updated = timezone.now()
|
||||||
|
|
||||||
|
def init_spt(self, code):
|
||||||
|
"""Initial setting of spotify tokens from user accept code"""
|
||||||
|
data = spt.get_token_json(
|
||||||
|
grant_type='authorization_code',
|
||||||
|
code=code
|
||||||
|
)
|
||||||
|
self.save_spt(data)
|
||||||
|
|
||||||
|
def refresh_spt(self):
|
||||||
|
"""Refreshes expired access token using stored refresh token"""
|
||||||
|
if self.spt_refresh_token:
|
||||||
|
data = spt.get_token_json(
|
||||||
|
grant_type='refresh_token',
|
||||||
|
refresh_token=self.spt_refresh_token
|
||||||
|
)
|
||||||
|
self.save_spt(data)
|
||||||
|
|
||||||
|
def save_spt(self, data):
|
||||||
|
"""Saves tokens from json response"""
|
||||||
|
access = data.get('access_token', None)
|
||||||
|
refresh = data.get('refresh_token', self.spt_refresh_token)
|
||||||
|
expires = data.get('expires_in', 3600)
|
||||||
|
self.spt_access_token = access
|
||||||
|
self.spt_refresh_token = refresh
|
||||||
|
self.spt_expires = timezone.now() + timedelta(seconds=expires - 300)
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
def unlink_spt(self):
|
||||||
|
self.spt_access_token = None
|
||||||
|
self.spt_refresh_token = None
|
||||||
|
self.spt_expires = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def can_spt(self):
|
||||||
|
return (
|
||||||
|
self.spt_access_token and
|
||||||
|
self.spt_expires and
|
||||||
|
(timezone.now() < self.spt_expires)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_or_update_spt(self):
|
||||||
|
if self.spt_refresh_token:
|
||||||
|
if not self.can_spt:
|
||||||
|
self.refresh_spt()
|
||||||
|
return self.spt_access_token
|
||||||
|
return None
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
self.update_quota()
|
self.update_quota()
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from django.db import models
|
|||||||
from random import choice
|
from random import choice
|
||||||
from .album import Album
|
from .album import Album
|
||||||
from .artist import Artist
|
from .artist import Artist
|
||||||
|
from .vote import Vote
|
||||||
import re
|
import re
|
||||||
|
|
||||||
class TrackManager(models.Manager):
|
class TrackManager(models.Manager):
|
||||||
@@ -30,6 +31,10 @@ class Track(models.Model):
|
|||||||
def link(self):
|
def link(self):
|
||||||
return f'https://open.spotify.com/track/{self.id}'
|
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):
|
def is_duplicate_of(self):
|
||||||
tracks = Track.objects.exclude(id=self.id).filter(name__startswith=self.name_sanitized)
|
tracks = Track.objects.exclude(id=self.id).filter(name__startswith=self.name_sanitized)
|
||||||
artists = [artist.name for artist in self.artists.all()]
|
artists = [artist.name for artist in self.artists.all()]
|
||||||
@@ -37,6 +42,7 @@ class Track(models.Model):
|
|||||||
tracks = tracks.filter(artists__name__exact=artist)
|
tracks = tracks.filter(artists__name__exact=artist)
|
||||||
return tracks.first()
|
return tracks.first()
|
||||||
|
|
||||||
|
|
||||||
id = models.CharField(primary_key=True, max_length=128)
|
id = models.CharField(primary_key=True, max_length=128)
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
artists = models.ManyToManyField(Artist)
|
artists = models.ManyToManyField(Artist)
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from . import Track
|
|
||||||
|
|
||||||
class Vote(models.Model):
|
class Vote(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ["user", "track"]
|
unique_together = ["user", "track"]
|
||||||
track = models.ForeignKey(Track, on_delete=models.CASCADE)
|
track = models.ForeignKey('Track', on_delete=models.CASCADE)
|
||||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
points = models.IntegerField()
|
points = models.IntegerField()
|
||||||
|
|||||||
+50
-9
@@ -3,46 +3,75 @@ import os
|
|||||||
import re
|
import re
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
|
|
||||||
class Spotify():
|
class Spotify():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.token = None
|
self.token = None
|
||||||
self.valid_until = None
|
self.valid_until = None
|
||||||
|
|
||||||
|
def redirect_uri(self):
|
||||||
|
return settings.CURRENT_HOST + reverse('spotify-callback')
|
||||||
|
|
||||||
def token_valid(self):
|
def token_valid(self):
|
||||||
if self.token and self.valid_until and (datetime.now() < self.valid_until):
|
if self.token and self.valid_until and (datetime.now() < self.valid_until):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_token(self):
|
def get_token_json(self, grant_type, code=None, refresh_token=None):
|
||||||
if self.token_valid():
|
|
||||||
print("Token still valid")
|
|
||||||
return self.token
|
|
||||||
print("New token")
|
|
||||||
url = 'https://accounts.spotify.com/api/token'
|
url = 'https://accounts.spotify.com/api/token'
|
||||||
headers = {
|
headers = {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
'Authorization': 'Basic ' + os.getenv('SPOTIFY_ENCODED_ID')
|
'Authorization': 'Basic ' + os.getenv('SPOTIFY_ENCODED_ID')
|
||||||
}
|
}
|
||||||
data = {
|
data = {
|
||||||
'grant_type': 'client_credentials'
|
'grant_type': grant_type
|
||||||
}
|
}
|
||||||
|
if code:
|
||||||
|
data['code'] = code
|
||||||
|
data['redirect_uri'] = self.redirect_uri()
|
||||||
|
if refresh_token:
|
||||||
|
data['refresh_token'] = refresh_token
|
||||||
r = requests.post(url, headers=headers, data=data)
|
r = requests.post(url, headers=headers, data=data)
|
||||||
data = r.json()
|
return r.json()
|
||||||
|
|
||||||
|
def get_system_token(self):
|
||||||
|
if self.token_valid():
|
||||||
|
return self.token
|
||||||
|
data = self.get_token_json('client_credentials')
|
||||||
self.token = data["access_token"]
|
self.token = data["access_token"]
|
||||||
self.valid_until = datetime.now() + timedelta(seconds=data["expires_in"]-300)
|
self.valid_until = datetime.now() + timedelta(seconds=data["expires_in"]-300)
|
||||||
return self.token
|
return self.token
|
||||||
|
|
||||||
|
def get_user_token(self, code):
|
||||||
|
data = self.get_token_json('authorization_code', code, redirect=True)
|
||||||
|
print(data)
|
||||||
|
return data
|
||||||
|
return (data.get('access_token', None), data.get('refresh_token', None))
|
||||||
|
|
||||||
|
def get_oauth_redirect(self):
|
||||||
|
scopes = ['user-read-private', 'user-read-email']
|
||||||
|
CLIENT_ID = 'bcc523219d1d4248a7e8892e809a5767' #TODO: delet.
|
||||||
|
url = f'https://accounts.spotify.com/authorize?'
|
||||||
|
url += f'client_id={CLIENT_ID}&'
|
||||||
|
url += f'response_type=code&'
|
||||||
|
url += f'scope={"%20".join(scopes)}&'
|
||||||
|
url += f'redirect_uri={self.redirect_uri()}'
|
||||||
|
print(url)
|
||||||
|
return url
|
||||||
|
|
||||||
def unshort(self, url):
|
def unshort(self, url):
|
||||||
"""Converts a spotify.link url into a normal spotify ID"""
|
"""Converts a spotify.link url into a normal spotify URL with ID"""
|
||||||
r = requests.get(url, allow_redirects=False)
|
r = requests.get(url, allow_redirects=False)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
return r.headers["Location"]
|
return r.headers["Location"]
|
||||||
|
|
||||||
def get_song_info(self, spotify_id):
|
def get_song_info(self, spotify_id):
|
||||||
token = self.get_token()
|
token = self.get_system_token()
|
||||||
url = 'https://api.spotify.com/v1/tracks/' + spotify_id
|
url = 'https://api.spotify.com/v1/tracks/' + spotify_id
|
||||||
headers = {
|
headers = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -51,3 +80,15 @@ class Spotify():
|
|||||||
r = requests.get(url, headers=headers)
|
r = requests.get(url, headers=headers)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
return r.json()
|
return r.json()
|
||||||
|
|
||||||
|
def get_profile(self, access_token):
|
||||||
|
url = 'https://api.spotify.com/v1/me'
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': 'Bearer ' + access_token
|
||||||
|
}
|
||||||
|
r = requests.get(url, headers=headers)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.json()
|
||||||
|
|
||||||
|
spt = Spotify()
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 378 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -477,11 +477,27 @@ input[type="range"]#volume::-webkit-slider-thumb {
|
|||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings .admin-panel {
|
.settings .icon {
|
||||||
background-image: url(img/gears.png);
|
|
||||||
height: 40px;
|
height: 40px;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 50% 50%;
|
background-position: 50% 50%;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings .admin-panel {
|
||||||
|
background-image: url(img/gears.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings .spotify {
|
||||||
|
background-image: url(img/spotify.png);
|
||||||
|
background-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings #spotify-cancel {
|
||||||
|
background-image: url(img/spotify-cancel.png);
|
||||||
|
background-size: 16px;
|
||||||
|
background-position: 50% 50%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{% extends "Base.html" %}
|
||||||
|
|
||||||
|
{% block window-title %}
|
||||||
|
Nomineren
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main-content %}
|
||||||
|
|
||||||
|
{% if tracks %}
|
||||||
|
{% for track in tracks %}
|
||||||
|
<p>{{track}}: {{track.score}}</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
Hoe veel nummers wil je?
|
||||||
|
<input type="number" id="count" name="count">
|
||||||
|
<input type="submit" value="OK" >
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -13,6 +13,24 @@ Instellingen
|
|||||||
<input type="submit" value="" class="icon admin-panel" />
|
<input type="submit" value="" class="icon admin-panel" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
{% if sptDisplayName %}
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="field-row settings">
|
||||||
|
<label>Spotify gekoppeld:</label>
|
||||||
|
<span>{{sptDisplayName}}</span>
|
||||||
|
<input type="hidden" id="unlink-spotify" name="unlink-spotify" value="true" />
|
||||||
|
<input type="submit" id="spotify-cancel" value=""/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<form action="{% url 'spotify' %}">
|
||||||
|
<div class="field-row settings">
|
||||||
|
<label>Link je spotify:</label>
|
||||||
|
<input type="submit" value="" class="icon spotify" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@@ -32,9 +50,8 @@ Instellingen
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
<div class="field-row settings">
|
<div class="field-row settings">
|
||||||
<label>Nominatie quota:</label>
|
<label>Nominatie quota:</label>
|
||||||
<span>{{user.profile.quota|floatformat:3}}</span>
|
<span>{{user.profile.quota|floatformat:3}}</span>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -18,18 +18,6 @@ Stemmen
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Hoeveel sterren geef jij dit?</legend>
|
<legend>Hoeveel sterren geef jij dit?</legend>
|
||||||
<div class="star-wrapper">
|
<div class="star-wrapper">
|
||||||
<a
|
|
||||||
hx-vals='{"vote": "-2"}'
|
|
||||||
hx-post="{% url 'vote' %}"
|
|
||||||
></a>
|
|
||||||
<a
|
|
||||||
hx-vals='{"vote": "-1"}'
|
|
||||||
hx-post="{% url 'vote' %}"
|
|
||||||
></a>
|
|
||||||
<a
|
|
||||||
hx-vals='{"vote": "0"}'
|
|
||||||
hx-post="{% url 'vote' %}"
|
|
||||||
></a>
|
|
||||||
<a
|
<a
|
||||||
hx-vals='{"vote": "1"}'
|
hx-vals='{"vote": "1"}'
|
||||||
hx-post="{% url 'vote' %}"
|
hx-post="{% url 'vote' %}"
|
||||||
@@ -38,13 +26,25 @@ Stemmen
|
|||||||
hx-vals='{"vote": "2"}'
|
hx-vals='{"vote": "2"}'
|
||||||
hx-post="{% url 'vote' %}"
|
hx-post="{% url 'vote' %}"
|
||||||
></a>
|
></a>
|
||||||
|
<a
|
||||||
|
hx-vals='{"vote": "3"}'
|
||||||
|
hx-post="{% url 'vote' %}"
|
||||||
|
></a>
|
||||||
|
<a
|
||||||
|
hx-vals='{"vote": "4"}'
|
||||||
|
hx-post="{% url 'vote' %}"
|
||||||
|
></a>
|
||||||
|
<a
|
||||||
|
hx-vals='{"vote": "5"}'
|
||||||
|
hx-post="{% url 'vote' %}"
|
||||||
|
></a>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{% if undo %}
|
{% if undo %}
|
||||||
<!--<form class="undo-wrapper" method="post" action="{% url 'undo' %}" hx-vals='{"spotify_id": "{{ undo.track.id }}"}' >-->
|
<!--<form class="undo-wrapper" method="post" action="{% url 'undo' %}" hx-vals='{"spotify_id": "{{ undo.track.id }}"}' >-->
|
||||||
<div class="undo-wrapper" hx-vals='{"spotify_id": "{{ undo.track.id }}"}' >
|
<div class="undo-wrapper" hx-vals='{"spotify_id": "{{ undo.track.id }}"}' >
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>Je hebt {{undo.track}} een score van {{undo.points | add:3}} sterren gegeven!</p>
|
<p>Je hebt {{undo.track}} een score van {{undo.points}} sterren gegeven!</p>
|
||||||
<button class="undo" hx-post="{% url 'undo' %}" >Undo</button>
|
<button class="undo" hx-post="{% url 'undo' %}" >Undo</button>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ urlpatterns = [
|
|||||||
path('vote/', views.VoteView.as_view(), name="vote"),
|
path('vote/', views.VoteView.as_view(), name="vote"),
|
||||||
path('vote/undo', views.UndoView.as_view(), name="undo"),
|
path('vote/undo', views.UndoView.as_view(), name="undo"),
|
||||||
path('settings/', views.SettingsView.as_view(), name="settings"),
|
path('settings/', views.SettingsView.as_view(), name="settings"),
|
||||||
|
path('settings/make-playlist', views.PlaylistMake.as_view(), name="playlist"),
|
||||||
path('overview/', views.OverView.as_view(), name="overview"),
|
path('overview/', views.OverView.as_view(), name="overview"),
|
||||||
|
path('spotify/', views.SpotifyView.as_view(), name="spotify"),
|
||||||
|
path('spotify/callback', views.SpotifyCallbackView.as_view(), name="spotify-callback"),
|
||||||
path('', views.AuthView.as_view()),
|
path('', views.AuthView.as_view()),
|
||||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|||||||
+61
-8
@@ -3,15 +3,15 @@ from django.views import View
|
|||||||
from django.http import HttpResponse, HttpResponseRedirect
|
from django.http import HttpResponse, HttpResponseRedirect
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.db.models import Avg
|
||||||
|
from django.urls import reverse
|
||||||
import re
|
import re
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from .models import Track, Artist, Album, Vote, Background, Profile
|
from .models import Track, Artist, Album, Vote, Background, Profile
|
||||||
from .utils import from_json, get_unvoted
|
from .utils import from_json, get_unvoted
|
||||||
from . import spotify
|
from .spotify import spt
|
||||||
from .tasks import get_banter, get_and_dither_image
|
from .tasks import get_banter, get_and_dither_image
|
||||||
|
|
||||||
spt = spotify.Spotify()
|
|
||||||
|
|
||||||
class AuthView(View):
|
class AuthView(View):
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
@@ -29,7 +29,7 @@ class VoteView(LoginRequiredMixin, View):
|
|||||||
try:
|
try:
|
||||||
spotify_id = self.request.POST['spotify_id']
|
spotify_id = self.request.POST['spotify_id']
|
||||||
score = int(self.request.POST['vote'])
|
score = int(self.request.POST['vote'])
|
||||||
score = min(max(-2, score), 2)
|
score = min(max(1, score), 5)
|
||||||
track = Track.objects.get(pk=spotify_id)
|
track = Track.objects.get(pk=spotify_id)
|
||||||
try:
|
try:
|
||||||
Vote.objects.get(user=request.user, track=track)
|
Vote.objects.get(user=request.user, track=track)
|
||||||
@@ -82,7 +82,8 @@ class NominateView(LoginRequiredMixin, View):
|
|||||||
except Track.DoesNotExist:
|
except Track.DoesNotExist:
|
||||||
try:
|
try:
|
||||||
json = spt.get_song_info(spotify_id)
|
json = spt.get_song_info(spotify_id)
|
||||||
except:
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
return TemplateResponse(request, "Nominate.html", {"error": "Fout bij het ophalen van het liedje."})
|
return TemplateResponse(request, "Nominate.html", {"error": "Fout bij het ophalen van het liedje."})
|
||||||
|
|
||||||
# Album artists
|
# Album artists
|
||||||
@@ -133,12 +134,22 @@ class SettingsView(LoginRequiredMixin, View):
|
|||||||
"backgrounds": backgrounds,
|
"backgrounds": backgrounds,
|
||||||
"currentBackground": (profile.background.id if profile.background else 1)
|
"currentBackground": (profile.background.id if profile.background else 1)
|
||||||
}
|
}
|
||||||
|
spt_token = profile.get_or_update_spt()
|
||||||
|
if spt_token:
|
||||||
|
context["sptDisplayName"] = spt.get_profile(spt_token).get('display_name')
|
||||||
|
|
||||||
return TemplateResponse(request, "Settings.html", context)
|
return TemplateResponse(request, "Settings.html", context)
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
try:
|
try:
|
||||||
bg = Background.objects.get(pk=request.POST['background'])
|
bg = request.POST.get('background', None)
|
||||||
|
unlink_spotify = request.POST.get('unlink-spotify', None)
|
||||||
(profile,_) = Profile.objects.get_or_create(user=request.user)
|
(profile,_) = Profile.objects.get_or_create(user=request.user)
|
||||||
profile.background = bg
|
if bg:
|
||||||
|
bg = Background.objects.get(pk=request.POST['background'])
|
||||||
|
profile.background = bg
|
||||||
|
if unlink_spotify:
|
||||||
|
print("unlink spt")
|
||||||
|
profile.unlink_spt()
|
||||||
profile.save()
|
profile.save()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
@@ -183,4 +194,46 @@ class OverView(LoginRequiredMixin, View):
|
|||||||
context = {
|
context = {
|
||||||
"artists": artists_ordered
|
"artists": artists_ordered
|
||||||
}
|
}
|
||||||
return TemplateResponse(request, "Overview.html", context)
|
return TemplateResponse(request, "Overview.html", context)
|
||||||
|
|
||||||
|
class PlaylistMake(LoginRequiredMixin, View):
|
||||||
|
def get(self, request, count=None):
|
||||||
|
context = {}
|
||||||
|
if count:
|
||||||
|
#tracks = Track.objects.order_by('score')[count]
|
||||||
|
tracks = Track.objects.annotate(average_points=Avg('vote__points')).order_by('-average_points')[:count]
|
||||||
|
context["tracks"] = tracks
|
||||||
|
return TemplateResponse(request, "PlaylistMaker.html", context)
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
count = int(self.request.POST['count'])
|
||||||
|
return self.get(request, count=count)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return self.get(request)
|
||||||
|
|
||||||
|
class SpotifyView(LoginRequiredMixin, View):
|
||||||
|
def get(self, request):
|
||||||
|
url = spt.get_oauth_redirect()
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
class SpotifyCallbackView(LoginRequiredMixin, View):
|
||||||
|
def get(self, request):
|
||||||
|
error = self.request.GET.get('error')
|
||||||
|
code = self.request.GET.get('code')
|
||||||
|
if error:
|
||||||
|
return TemplateResponse(request, "Nominate.html", {"error": "Je moet wel accepteren, pannenkoek."})
|
||||||
|
elif code:
|
||||||
|
(profile,_) = Profile.objects.get_or_create(user=request.user)
|
||||||
|
profile.init_spt(code)
|
||||||
|
# data = spt.get_user_token(code)
|
||||||
|
# access = data.get('access_token', None)
|
||||||
|
# refresh = data.get('refresh_token', None)
|
||||||
|
# expires = data.get('expires_in', 3600)
|
||||||
|
|
||||||
|
# if access and refresh:
|
||||||
|
# profile.set_spotify(access, refresh, expires)
|
||||||
|
# else:
|
||||||
|
# return TemplateResponse(request, "Nominate.html", {"error": "No."})
|
||||||
|
return HttpResponseRedirect(reverse('settings'))
|
||||||
|
#return TemplateResponse(request, "Nominate.html", {"warning": code})
|
||||||
|
|||||||
Reference in New Issue
Block a user