commit b1c36bd22c11442c6a1644ccb41aee87942ec42c Author: brandon Date: Sat Apr 20 18:30:12 2024 -0700 inital version, simple layout and functionality diff --git a/__pycache__/yamlcon.cpython-312.pyc b/__pycache__/yamlcon.cpython-312.pyc new file mode 100644 index 0000000..8f43f22 Binary files /dev/null and b/__pycache__/yamlcon.cpython-312.pyc differ diff --git a/code b/code new file mode 100644 index 0000000..fc99224 --- /dev/null +++ b/code @@ -0,0 +1 @@ +AQA8p4IgPYH0j9TIUFR4m5zAKPgvPzhvW07iCLAUYq-7sWyhxTTDRiWZaocH01HomhYoGZnVarc2SGUH4Buu9ox22lQ0e7z4AnglirOqF8I24v4zZveuiOPuLjet4YFY9rCY9TdtGmaUE1Y710tdgF7_ZBT4V2fuFSM0i9qXML37rZBS_DVmWlbVyLi-RKOeT-EIktYsTNfV45ajoe-GCB7eL5eFit8nGGjBokIXM0w14m004GtnvjfcazBaJqS6XlqU80VB82OTQauN7fyckTEYMUalhfM20ZE2p8D7qCg \ No newline at end of file diff --git a/spotifycontroller.py b/spotifycontroller.py new file mode 100644 index 0000000..546ea1f --- /dev/null +++ b/spotifycontroller.py @@ -0,0 +1,150 @@ +from flask import Flask, render_template, request, url_for, redirect +import time +import requests +from urllib.parse import urlencode +import webbrowser +import base64 +import json +import os + +app = Flask(__name__) + + +client_id = '1cb8bc27872c4bcaaad0e95f123b4f7d' +client_secret = '9893dfb6d9eb43eebf082f9173ce937c' +redirect_uri = 'http://127.0.0.1:8888/callback' +encoded_creds = base64.b64encode(client_id.encode() + b':' + client_secret.encode()).decode("utf-8") + + +headers = { + "client_id": client_id, + "response_type": "code", + "redirect_uri": redirect_uri, + "scope": "user-read-playback-state,user-modify-playback-state,user-library-read,user-library-modify" +} + +token_headers = { + "Authorization": "Basic " + encoded_creds, + "Content-Type": "application/x-www-form-urlencoded" +} + +song_info = { + 'name': "None", + 'artist': "None", + 'album': "None", + 'image': "None" +} + +@app.route('/') +def index(): + global code + if os.path.exists('code'): + with open('code', 'r') as file: + code = file.read() + return redirect(url_for('webapp')) + else: + return redirect("https://accounts.spotify.com/authorize?" + urlencode(headers)) + # return render_template('index.html') + +# @app.route('/update') +# def update(): +# # Generate new information +# new_info = generate_new_info() + +# # Wait for 1 second +# time.sleep(1) + +# return new_info + +@app.route('/webapp', methods=['GET', 'POST']) +def webapp(): + global access_token + # NEED TO FIND A BETTER WAY THAT DOESN'T INVOLVE A TRY EXCEPT BLOCK + if 'code' not in globals() or not code: + return redirect(url_for('index')) + token_data = { + "grant_type": "authorization_code", + "code": code, + "redirect_uri": redirect_uri + } + + access_object = requests.post("https://accounts.spotify.com/api/token", data=token_data, headers=token_headers) + if "error" in access_object.json(): + if os.path.exists('code'): + os.remove('code') + return redirect(url_for('index')) + access_token = access_object.json()["access_token"] + + return render_template('webapp.html', song_info=song_info) + +@app.route('/callback', methods=['GET']) +def callback(): + global code + code = request.args.get('code') + with open('code', 'w') as file: + file.write(code) + return redirect(url_for('webapp')) + +@app.route('/appdata') +def appdata(): + global access_token + user_headers = { + "Authorization": "Bearer " + access_token, + "Content-Type": "application/json" + } + + currently_playing = requests.get("https://api.spotify.com/v1/me/player/currently-playing", headers=user_headers) + + + if currently_playing.json()["is_playing"] == True: + return { 'id': currently_playing.json()["item"]["id"], + 'name': currently_playing.json()["item"]["name"], + 'artist': currently_playing.json()["item"]["artists"][0]["name"], + 'album': currently_playing.json()["item"]["album"]["name"], + 'image': currently_playing.json()["item"]["album"]["images"][0]["url"], + 'is_playing': currently_playing.json()["is_playing"], + 'progress_ms': currently_playing.json()["progress_ms"], + 'duration_ms': currently_playing.json()["item"]["duration_ms"], + 'is_liked': requests.get("https://api.spotify.com/v1/me/tracks/contains?ids=" + currently_playing.json()["item"]["id"], headers=user_headers).json()[0] + } + elif currently_playing.json()["is_playing"] == False: + return { 'name': "Not Playing", + 'artist': "Not Playing", + 'album': "Not Playing", + 'image': "Not Playing" + } + else: + return { 'name': "Error", + 'artist': "Error", + 'album': "Error", + 'image': "Error" + } + +@app.route('/control', methods=['POST']) +def control(): + global access_token + user_headers = { + "Authorization": "Bearer " + access_token, + "Content-Type": "application/json" + } + + if request.form.get('command') == "pause": + requests.put("https://api.spotify.com/v1/me/player/pause", headers=user_headers) + elif request.form.get('command') == "play": + requests.put("https://api.spotify.com/v1/me/player/play", headers=user_headers) + elif request.form.get('command') == "next": + requests.post("https://api.spotify.com/v1/me/player/next", headers=user_headers) + elif request.form.get('command') == "previous": + requests.post("https://api.spotify.com/v1/me/player/previous", headers=user_headers) + elif request.form.get('command') == "restart": + requests.put("https://api.spotify.com/v1/me/player/seek?position_ms=0", headers=user_headers) + elif request.form.get('command') == "like": + requests.put("https://api.spotify.com/v1/me/tracks?ids=" + request.form.get('id'), headers=user_headers) + elif request.form.get('command') == "unlike": + requests.delete("https://api.spotify.com/v1/me/tracks?ids=" + request.form.get('id'), headers=user_headers) + + print(request.form.get('command')) + return ('', 204) + +if __name__ == '__main__': + app.run(port=8888, debug=True) \ No newline at end of file diff --git a/templates/webapp.html b/templates/webapp.html new file mode 100644 index 0000000..bf1409d --- /dev/null +++ b/templates/webapp.html @@ -0,0 +1,158 @@ + + + + + + Updating Value + + + + + Song Image +
+

{{ song_info['name'] }}

+

{{ song_info['artist'] }}

+ +

+ + + + +

+
+
+
+
+ + + diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..291aa16 --- /dev/null +++ b/todo.txt @@ -0,0 +1,12 @@ +song name is successfully on the website. +next task: +have this update every 1 or 2 seconds. + + +04-18-24: +make it so when the js app calls the /appdata endpoint it sends the song id, +ONLY if the song id is different then the fetched one should the endpoint +provide updated song info, otherwise have it return just song progress ONLY. + +include color calculation, probably in python then give color value +to js app, but maybe have js app do it from album art, explore which is better. \ No newline at end of file diff --git a/yamlcon.py b/yamlcon.py new file mode 100644 index 0000000..87bc3ba --- /dev/null +++ b/yamlcon.py @@ -0,0 +1,19 @@ +import yaml + +def load(path): + with open(path, 'r') as file: + try: + data = yaml.safe_load(file) + return data + except yaml.YAMLError as e: + print(f"Error reading YAML file {path}: {e}") + return None + +def save(path, data): + with open(path, 'w') as file: + try: + yaml.dump(data, file) + return True + except yaml.YAMLError as e: + print(f"Error writing to YAML file {path}: {e}") + return None \ No newline at end of file