from flask import Flask, render_template, request, url_for, redirect, send_from_directory import requests from urllib.parse import urlencode import base64 import os import _canvas as SpotifyCanvas import time import syncedlyrics app = Flask(__name__) if os.path.exists('client_id'): with open('client_id', 'r') as file: client_id = file.read() print(client_id) if os.path.exists('client_secret'): with open('client_secret', 'r') as file: client_secret = file.read() 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" } data = { 'name': "Loading...", 'artist': "", 'album': "", 'image': "https://cdn.pixabay.com/animation/2023/05/02/04/29/04-29-03-511_512.gif" } @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', data=data) @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 stime = time.time() try: user_headers = { "Authorization": "Bearer " + access_token, "Content-Type": "application/json" } except NameError: return { 'reload': True } currently_playing = requests.get("https://api.spotify.com/v1/me/player/currently-playing", headers=user_headers) if currently_playing.content: if currently_playing.json()["is_playing"] is True and currently_playing.json()["item"]["id"] == request.args.get('id'): print("QUICK" + str(time.time() - stime)) return { 'progress_ms': currently_playing.json()["progress_ms"], } elif currently_playing.json()["is_playing"] is True and currently_playing.json()["item"]["id"] != request.args.get('id'): print("FULL" + str(time.time() - stime)) 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], 'canvas': False, 'fetchlyrics': 'fetch' } elif currently_playing.json()["is_playing"] is False: return { 'is_playing': False } else: return { 'name': "Error", 'artist': "Error" } else: return { 'is_playing': False } @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) return { 'is_playing': False } elif request.form.get('command') == "play": requests.put("https://api.spotify.com/v1/me/player/play", headers=user_headers) return { 'is_playing': True } 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) return { 'is_liked': True } elif request.form.get('command') == "unlike": requests.delete("https://api.spotify.com/v1/me/tracks?ids=" + request.form.get('id'), headers=user_headers) return { 'is_liked': False } print(request.form.get('command')) return ('', 204) @app.route('/icons/') def icons(filename): return send_from_directory('icons', filename) @app.route('/canvas') def canvas(): print("CANVAS") id = request.args.get('id') try: return { 'canvas_url': SpotifyCanvas.get_canvas_for_track(SpotifyCanvas.get_access_token(), id) } except AttributeError: return { 'canvas_url': None } @app.route('/lyrics') def lyrics(): name = request.args.get('name') artist = request.args.get('artist') if name and artist is not None: full_lyrics = syncedlyrics.search("[" + name + "] [" + artist + "]") else: return { 'lyrics': '' } if full_lyrics is None: return { 'lyrics': "no lyrics" } return { 'lyrics': full_lyrics } if __name__ == '__main__': app.run(port=8888, debug=True)