Browse Source

Support seamless authentication

pull/3/head
Wesley Kerfoot 5 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.
* Create a `.env` or `.envrc` file with contents like this, put it wherever you
want.
* Go to "Edit Settings" in your newly created app, then add `http://localhost`
as a redirect URI and hit "Save"
```
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'
```
* Find your spotify username [here](https://www.spotify.com/us/account/overview/)
* You can find the values for `SPOTIPY_CLIENT_ID` and `SPOTIPY_CLIENT_SECRET`
on the page for your application that you just created.
* Now you can run `spotsync --username=username --host=my_mpd_host` where
`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/)
* Now you can run `spotsync` with your `.env` file sourced (e.g. `source .env`)
* 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
spotsync.

3
requirements.txt

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

3
setup.py

@ -15,7 +15,8 @@ setuptools.setup(
packages=setuptools.find_packages(),
install_requires = [
"spotipy>=2.4.4",
"python-mpd2>=1.0.0"
"python-mpd2>=1.0.0",
"bottle>=0.12.16"
],
classifiers= [
"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
from spotipy.oauth2 import SpotifyClientCredentials
from spotipy.util import prompt_for_user_token
from mpd import MPDClient
from mpd.base import CommandError
from collections import defaultdict
from re import sub
from os import environ
import spotipy.util as util
from spotify_mpd_sync.msplaylist.authenticate import run_server, prompt_for_user_token
class Spotify():
def __init__(self):
run_server()
self.username = environ.get("SPOTIFY_USERNAME")
self.client_credentials_manager = SpotifyClientCredentials()
self.sp = spotipy.Spotify(
client_credentials_manager=self.client_credentials_manager
)
scope = "playlist-read-private"
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.connect("127.0.0.1", 6600)

Loading…
Cancel
Save