Browse Source

Support seamless authentication

pull/3/head
Wesley Kerfoot 6 years ago
parent
commit
1cc1ef8d63
  1. 22
      README.md
  2. 3
      requirements.txt
  3. 3
      setup.py
  4. 94
      spotify_mpd_sync/msplaylist/authenticate.py
  5. 19
      spotify_mpd_sync/msplaylist/spotify.py

22
README.md

@ -7,19 +7,15 @@
* Go to [https://developer.spotify.com/dashboard/applications](https://developer.spotify.com/dashboard/applications) and create an application. Call it whatever you want. * Go to [https://developer.spotify.com/dashboard/applications](https://developer.spotify.com/dashboard/applications) and create an application. Call it whatever you want.
* Create a `.env` or `.envrc` file with contents like this, put it wherever you * Go to "Edit Settings" in your newly created app, then add `http://localhost`
want. as a redirect URI and hit "Save"
``` * Find your spotify username [here](https://www.spotify.com/us/account/overview/)
export SPOTIPY_CLIENT_ID='YOUR_CLIENT_ID'
export SPOTIPY_CLIENT_SECRET='YOUR_CLIENT_SECRET'
export SPOTIPY_REDIRECT_URI='http://localhost'
export SPOTIFY_USERNAME='YOUR_SPOTIFY_USERNAME'
```
* You can find the values for `SPOTIPY_CLIENT_ID` and `SPOTIPY_CLIENT_SECRET` * Now you can run `spotsync --username=username --host=my_mpd_host` where
on the page for your application that you just created. `username` is your username from before, and `my_mpd_host` is the host you
are running MPD on (defaults to `localhost` if you do not pass it)
* You can find your spotify username [here](https://www.spotify.com/us/account/overview/) * You will be prompted to grant permission to the app, once that's done, it
will cache the credentials locally and you should be able to just run
* Now you can run `spotsync` with your `.env` file sourced (e.g. `source .env`) spotsync.

3
requirements.txt

@ -1,9 +1,12 @@
bottle==0.12.16
certifi==2019.3.9 certifi==2019.3.9
cffi==1.12.3 cffi==1.12.3
chardet==3.0.4 chardet==3.0.4
httplib2==0.12.3
idna==2.8 idna==2.8
pycparser==2.19 pycparser==2.19
python-mpd2==1.0.0 python-mpd2==1.0.0
requests==2.21.0 requests==2.21.0
spotify-mpd-sync-weskerfoot==0.0.1
spotipy==2.4.4 spotipy==2.4.4
urllib3==1.24.2 urllib3==1.24.2

3
setup.py

@ -15,7 +15,8 @@ setuptools.setup(
packages=setuptools.find_packages(), packages=setuptools.find_packages(),
install_requires = [ install_requires = [
"spotipy>=2.4.4", "spotipy>=2.4.4",
"python-mpd2>=1.0.0" "python-mpd2>=1.0.0",
"bottle>=0.12.16"
], ],
classifiers= [ classifiers= [
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",

94
spotify_mpd_sync/msplaylist/authenticate.py

@ -0,0 +1,94 @@
# shows a user's playlists (need to be authenticated via oauth)
from __future__ import print_function
import os
import spotipy.oauth2 as oauth2
import spotipy
import queue
import threading
from bottle import route, run, response, request
auth_token_queue = queue.Queue()
@route('/')
def index():
auth_code = request.query.code
if auth_code:
auth_token_queue.put(auth_code)
return "It worked! You may close this tab now"
return "Oops! Something went wrong. Please file a bug report"
def run_server():
task = threading.Thread(target=lambda : run(host='localhost', port=8080))
task.start()
def prompt_for_user_token(username, scope=None, client_id = None,
client_secret = None, redirect_uri = None, cache_path = None):
"""
prompts the user to login if necessary and returns
the user token suitable for use with the spotipy.Spotify
constructor
Parameters:
- username - the Spotify username
- scope - the desired scope of the request
- client_id - the client id of your app
- client_secret - the client secret of your app
- redirect_uri - the redirect URI of your app
- cache_path - path to location to save tokens
"""
if not client_id:
client_id = os.getenv('SPOTIPY_CLIENT_ID')
if not client_secret:
client_secret = os.getenv('SPOTIPY_CLIENT_SECRET')
if not redirect_uri:
redirect_uri = os.getenv('SPOTIPY_REDIRECT_URI')
if not client_id:
print('''
You need to set your Spotify API credentials. You can do this by
setting environment variables like so:
export SPOTIPY_CLIENT_ID='your-spotify-client-id'
export SPOTIPY_CLIENT_SECRET='your-spotify-client-secret'
export SPOTIPY_REDIRECT_URI='your-app-redirect-url'
Get your credentials at
https://developer.spotify.com/my-applications
''')
raise spotipy.SpotifyException(550, -1, 'no credentials set')
cache_path = cache_path or ".cache-" + username
sp_oauth = oauth2.SpotifyOAuth(client_id, client_secret, redirect_uri,
scope=scope, cache_path=cache_path)
# try to get a valid token for this user, from the cache,
# if not in the cache, the create a new (this will send
# the user to a web page where they can authorize this app)
token_info = sp_oauth.get_cached_token()
if not token_info:
auth_url = sp_oauth.get_authorize_url()
try:
import webbrowser
webbrowser.open(auth_url)
print("Opened %s in your browser" % auth_url)
except:
print("Please navigate here: %s" % auth_url)
response = "localhost:8080?code=%s" % auth_token_queue.get()
auth_token_queue.task_done()
code = sp_oauth.parse_response_code(response)
token_info = sp_oauth.get_access_token(code)
# Auth'ed API request
if token_info:
return token_info['access_token']
else:
return None

19
spotify_mpd_sync/msplaylist/spotify.py

@ -2,19 +2,30 @@
import spotipy import spotipy
from spotipy.oauth2 import SpotifyClientCredentials from spotipy.oauth2 import SpotifyClientCredentials
from spotipy.util import prompt_for_user_token
from mpd import MPDClient from mpd import MPDClient
from mpd.base import CommandError from mpd.base import CommandError
from collections import defaultdict from collections import defaultdict
from re import sub from re import sub
from os import environ from os import environ
import spotipy.util as util
from spotify_mpd_sync.msplaylist.authenticate import run_server, prompt_for_user_token
class Spotify(): class Spotify():
def __init__(self): def __init__(self):
run_server()
self.username = environ.get("SPOTIFY_USERNAME") self.username = environ.get("SPOTIFY_USERNAME")
self.client_credentials_manager = SpotifyClientCredentials()
self.sp = spotipy.Spotify( scope = "playlist-read-private"
client_credentials_manager=self.client_credentials_manager
) token = prompt_for_user_token(self.username,
scope,
client_id=environ.get("SPOTIPY_CLIENT_ID"),
client_secret=environ.get("SPOTIPY_CLIENT_SECRET"),
redirect_uri=environ.get("SPOTIPY_REDIRECT_URI"))
if token:
self.sp = spotipy.Spotify(auth=token)
self.mpd_client = MPDClient() self.mpd_client = MPDClient()
self.mpd_client.connect("127.0.0.1", 6600) self.mpd_client.connect("127.0.0.1", 6600)

Loading…
Cancel
Save