|
@ -1,13 +1,10 @@ |
|
|
# imports {{{ # |
|
|
# imports {{{ # |
|
|
|
|
|
|
|
|
import math |
|
|
import math |
|
|
import random |
|
|
|
|
|
import requests |
|
|
|
|
|
import os |
|
|
import os |
|
|
import urllib |
|
|
import urllib |
|
|
import secrets |
|
|
import secrets |
|
|
import pprint |
|
|
import pprint |
|
|
import string |
|
|
|
|
|
from datetime import datetime |
|
|
from datetime import datetime |
|
|
|
|
|
|
|
|
from django.shortcuts import render, redirect |
|
|
from django.shortcuts import render, redirect |
|
@ -21,28 +18,8 @@ TIME_FORMAT = '%Y-%m-%d-%H-%M-%S' |
|
|
TRACKS_TO_QUERY = 200 |
|
|
TRACKS_TO_QUERY = 200 |
|
|
AUTH_SCOPE = ['user-library-read', 'user-read-recently-played',] |
|
|
AUTH_SCOPE = ['user-library-read', 'user-read-recently-played',] |
|
|
|
|
|
|
|
|
# generate_random_string {{{ # |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate_random_string(length): |
|
|
|
|
|
"""Generates a random string of a certain length |
|
|
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
|
length: the desired length of the randomized string |
|
|
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
|
A random string |
|
|
|
|
|
""" |
|
|
|
|
|
all_chars = string.ascii_letters + string.digits |
|
|
|
|
|
rand_str = "".join(random.choice(all_chars) for _ in range(length)) |
|
|
|
|
|
|
|
|
|
|
|
return rand_str |
|
|
|
|
|
|
|
|
|
|
|
# }}} generate_random_string # |
|
|
|
|
|
|
|
|
|
|
|
# index {{{ # |
|
|
# index {{{ # |
|
|
|
|
|
|
|
|
# Create your views here. |
|
|
|
|
|
def index(request): |
|
|
def index(request): |
|
|
return render(request, 'login/index.html') |
|
|
return render(request, 'login/index.html') |
|
|
|
|
|
|
|
@ -73,6 +50,8 @@ def spotify_login(request): |
|
|
|
|
|
|
|
|
# }}} spotify_login # |
|
|
# }}} spotify_login # |
|
|
|
|
|
|
|
|
|
|
|
# callback {{{ # |
|
|
|
|
|
|
|
|
def callback(request): |
|
|
def callback(request): |
|
|
""" Step 2 in authorization flow: Have your application request refresh and |
|
|
""" Step 2 in authorization flow: Have your application request refresh and |
|
|
access tokens; Spotify returns access and refresh tokens. |
|
|
access tokens; Spotify returns access and refresh tokens. |
|
@ -97,38 +76,8 @@ def callback(request): |
|
|
token_response['expires_in']) |
|
|
token_response['expires_in']) |
|
|
|
|
|
|
|
|
return render(request, 'login/scan.html', get_user_context(user_obj)) |
|
|
return render(request, 'login/scan.html', get_user_context(user_obj)) |
|
|
# return redirect('user/' + user_obj.secret) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_user(refresh_token, access_token, access_expires_in): |
|
|
|
|
|
"""Create a User object based on information returned from Step 2 (callback |
|
|
|
|
|
function) of auth flow. |
|
|
|
|
|
|
|
|
|
|
|
:refresh_token: Used to renew access tokens. |
|
|
|
|
|
:access_token: Used in Spotify API calls. |
|
|
|
|
|
:access_expires_in: How long the access token last in seconds. |
|
|
|
|
|
|
|
|
|
|
|
:returns: The newly created User object. |
|
|
|
|
|
|
|
|
|
|
|
""" |
|
|
|
|
|
profile_response = requests.get('https://api.spotify.com/v1/me', |
|
|
|
|
|
headers={'Authorization': "Bearer " + access_token}).json() |
|
|
|
|
|
user_id = profile_response['id'] |
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
|
user_obj = User.objects.get(id=user_id) |
|
|
|
|
|
except User.DoesNotExist: |
|
|
|
|
|
# Python docs recommends 32 bytes of randomness against brute |
|
|
|
|
|
# force attacks |
|
|
|
|
|
user_obj = User.objects.create( |
|
|
|
|
|
id=user_id, |
|
|
|
|
|
secret=secrets.token_urlsafe(32), |
|
|
|
|
|
refresh_token=refresh_token, |
|
|
|
|
|
access_token=access_token, |
|
|
|
|
|
access_expires_in=access_expires_in, |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
return user_obj |
|
|
|
|
|
|
|
|
# }}} callback # |
|
|
|
|
|
|
|
|
# admin_graphs {{{ # |
|
|
# admin_graphs {{{ # |
|
|
|
|
|
|
|
|