asd
This commit is contained in:
commit
ac2893b991
4 changed files with 243 additions and 0 deletions
1
.cache
Normal file
1
.cache
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"access_token": "BQChu2C4bda7mJQi_xq_9-DRf3Vtq6hVwk88K3h1QXacIN8ppdFME-RZfy1wxJekQ__UVET_o9ZlWmD3nfqh1Otlbaenr0OwYGQlJDHSZYPBINUT0RbjkkCy5-2rNuqXEimVZpPf3ud9dYuHq4-hxJxrd1OdHi7fGhncF53qs4pulx1iPDVr5hDeJOO6vJh4A6X1NagW3nW8W1wxvesvlxaXeGE", "token_type": "Bearer", "expires_in": 3600, "scope": "user-modify-playback-state user-read-playback-state", "expires_at": 1736693329, "refresh_token": "AQDjS3e8vYiwJmfaksX3Bb-aS01v9UN0houDiFWvMMeJiCSv2fzNO4Gy81LAktHOgychbjD0e_ZC7m_HLJufAMQx3EeXn9HOz8Wo08MHfUaXHNaajKK5e7SIgev9H_2mU7g"}
|
66
app.py
Normal file
66
app.py
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
from flask import Flask, render_template, request, redirect, url_for, jsonify
|
||||||
|
from spotipy import Spotify
|
||||||
|
from spotipy.oauth2 import SpotifyOAuth
|
||||||
|
|
||||||
|
# Flask app
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
# Spotify API credentials
|
||||||
|
CLIENT_ID = "d599e0f7a26d419eb6ae618361e1538c"
|
||||||
|
CLIENT_SECRET = "af42c3dcdc90448087f8bc597ad551c6"
|
||||||
|
REDIRECT_URI = "https://localhost:8888/callback"
|
||||||
|
SCOPE = "user-modify-playback-state user-read-playback-state"
|
||||||
|
|
||||||
|
# Spotipy client
|
||||||
|
sp = Spotify(auth_manager=SpotifyOAuth(
|
||||||
|
client_id=CLIENT_ID,
|
||||||
|
client_secret=CLIENT_SECRET,
|
||||||
|
redirect_uri=REDIRECT_URI,
|
||||||
|
scope=SCOPE
|
||||||
|
))
|
||||||
|
|
||||||
|
# Home route
|
||||||
|
@app.route("/")
|
||||||
|
def home():
|
||||||
|
return render_template("index.html")
|
||||||
|
|
||||||
|
@app.route("/add", methods=["GET"])
|
||||||
|
def add_song():
|
||||||
|
# Get the song name from the query parameters
|
||||||
|
song_name = request.args.get("song_name")
|
||||||
|
if not song_name:
|
||||||
|
return jsonify({"error": "No song name provided."}), 400
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Search and add the song to the Spotify queue
|
||||||
|
search_results = sp.search(q=song_name, type="track", limit=1)
|
||||||
|
if search_results["tracks"]["items"]:
|
||||||
|
track_uri = search_results["tracks"]["items"][0]["uri"]
|
||||||
|
print(search_results["tracks"]["items"][0])
|
||||||
|
sp.add_to_queue(track_uri)
|
||||||
|
name = search_results["tracks"]["items"][0]["name"]
|
||||||
|
return jsonify({"message": f"'{name}' has been added to the queue."}), 200
|
||||||
|
else:
|
||||||
|
return jsonify({"error": "No matching track found."}), 404
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"error": str(e)}), 500
|
||||||
|
|
||||||
|
# Route to serve the queue table for iframe
|
||||||
|
@app.route("/queue_table")
|
||||||
|
def queue_table():
|
||||||
|
queue_data = sp.queue()
|
||||||
|
print(queue_data)
|
||||||
|
queue = []
|
||||||
|
if "queue" in queue_data and queue_data["queue"]:
|
||||||
|
for track in queue_data["queue"]:
|
||||||
|
track_name = track["name"]
|
||||||
|
artist_name = track["artists"][0]["name"]
|
||||||
|
queue.append({"track": track_name, "artist": artist_name})
|
||||||
|
current = None
|
||||||
|
if queue_data["currently_playing"]:
|
||||||
|
current = {"track":queue_data["currently_playing"]["name"], "artist":queue_data["currently_playing"]["artists"][0]["name"]}
|
||||||
|
return render_template("queue_table.html", queue=queue, length=len(queue), now_playing=current)
|
||||||
|
|
||||||
|
# Run the Flask app
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(port=80, host="0.0.0.0", debug=True)
|
113
templates/index.html
Normal file
113
templates/index.html
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Spotify Queue Manager</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
form {
|
||||||
|
margin: 20px auto;
|
||||||
|
}
|
||||||
|
input[type="text"] {
|
||||||
|
width: 80%;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
background-color: #000000;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
iframe {
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
margin-top: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Queue</h1>
|
||||||
|
<form id="addSongForm" onsubmit="addSong(event)">
|
||||||
|
<input type="text" id="songInput" name="song_name" placeholder="Adauga melodie sau artist " required>
|
||||||
|
<button type="submit">Adauga</button>
|
||||||
|
</form>
|
||||||
|
<div class="message" id="message"></div>
|
||||||
|
<!-- Queue Table Embedded in an iframe -->
|
||||||
|
<iframe src="/queue_table" id="queueIframe"></iframe>
|
||||||
|
<script>
|
||||||
|
// Function to handle song addition via GET request
|
||||||
|
async function addSong(event) {
|
||||||
|
event.preventDefault(); // Prevent the form from submitting normally
|
||||||
|
const songInput = document.getElementById("songInput");
|
||||||
|
const messageDiv = document.getElementById("message");
|
||||||
|
const songName = encodeURIComponent(songInput.value);
|
||||||
|
|
||||||
|
// Clear message and disable input/button during request
|
||||||
|
messageDiv.textContent = "Adding song...";
|
||||||
|
songInput.disabled = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Send GET request to add song
|
||||||
|
const response = await fetch(`/add?song_name=${songName}`);
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
// Update message based on the response
|
||||||
|
if (response.ok) {
|
||||||
|
messageDiv.textContent = data.message || "Song added successfully!";
|
||||||
|
messageDiv.className = "message success";
|
||||||
|
} else {
|
||||||
|
throw new Error(data.error || "Failed to add the song.");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
messageDiv.textContent = error.message;
|
||||||
|
messageDiv.className = "message error";
|
||||||
|
} finally {
|
||||||
|
// Re-enable input and clear it
|
||||||
|
songInput.disabled = false;
|
||||||
|
songInput.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload the iframe to reflect the updated queue
|
||||||
|
document.getElementById("queueIframe").contentWindow.location.reload();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
messageDiv.textContent = "";
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
|
// Adjust the iframe height dynamically to avoid scrollbars
|
||||||
|
function resizeIframe() {
|
||||||
|
const iframe = document.getElementById('queueIframe');
|
||||||
|
iframe.style.height = iframe.contentWindow.document.body.scrollHeight+20 + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize iframe after it loads and periodically refresh the iframe
|
||||||
|
const iframe = document.getElementById('queueIframe');
|
||||||
|
iframe.onload = resizeIframe;
|
||||||
|
setInterval(() => {
|
||||||
|
iframe.contentWindow.location.reload();
|
||||||
|
}, 15000);
|
||||||
|
|
||||||
|
// Add event listener for resize events
|
||||||
|
window.addEventListener('resize', resizeIframe);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
63
templates/queue_table.html
Normal file
63
templates/queue_table.html
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
color: #000000;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.now-playing {
|
||||||
|
text-align: center;
|
||||||
|
margin: 20px 0;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1em;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #000000;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<center>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Track</th>
|
||||||
|
<th>Artist</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for i in range(length) %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ i+1 }}</td>
|
||||||
|
<td>{{ queue[i].track }}</td>
|
||||||
|
<td>{{ queue[i].artist }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table></center>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue