Files
Video-Player-Controller/app.py
T
Media fc27feaea1 initial commmit
A video player controller for the video player node
2026-06-14 14:34:34 -05:00

253 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from flask import Flask, render_template_string, request, redirect, url_for, flash
import os
from controller_core import enqueue_download
app = Flask(__name__)
app.secret_key = os.environ.get("FLASK_SECRET_KEY", "dev-secret")
HTML_FORM = """
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>YouTube Playlist Submit</title>
<!-- Make it behave on mobile -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<style>
:root {
color-scheme: dark;
}
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
margin: 0;
padding: 0;
background: #020617;
color: #e5e7eb;
}
.page-wrapper {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 1.25rem;
}
.card {
width: 100%;
max-width: 520px;
background: rgba(15, 23, 42, 0.98);
padding: 1.75rem 1.5rem 1.4rem;
border-radius: 1rem;
box-shadow: 0 18px 45px rgba(0, 0, 0, 0.7);
border: 1px solid rgba(148, 163, 184, 0.35);
}
h2 {
margin: 0 0 0.4rem;
font-size: 1.35rem;
}
.subtitle {
margin: 0 0 1.1rem;
font-size: 0.95rem;
color: #9ca3af;
}
.flash {
margin-bottom: 0.75rem;
padding: 0.55rem 0.75rem;
border-radius: 0.6rem;
background: rgba(30, 64, 175, 0.35);
border: 1px solid rgba(129, 140, 248, 0.7);
font-size: 0.9rem;
}
.form-group {
margin-bottom: 0.85rem;
}
label {
display: block;
margin-bottom: 0.3rem;
font-size: 0.92rem;
}
input,
textarea {
width: 100%;
box-sizing: border-box;
padding: 0.7rem 0.85rem;
border-radius: 0.65rem;
border: 1px solid #4b5563;
background: #020617;
color: #e5e7eb;
font-size: 1rem;
}
input::placeholder,
textarea::placeholder {
color: #6b7280;
}
input:focus,
textarea:focus {
outline: 2px solid #38bdf8;
outline-offset: 2px;
border-color: #38bdf8;
}
textarea {
min-height: 3.2rem;
resize: vertical;
}
button {
width: 100%;
padding: 0.8rem 1.5rem;
border-radius: 999px;
border: none;
background: linear-gradient(135deg, #38bdf8, #6366f1);
color: #fff;
font-weight: 600;
font-size: 1rem;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
margin-top: 0.2rem;
}
button:active {
transform: scale(0.98);
}
.helper {
margin-top: 0.9rem;
font-size: 0.8rem;
color: #9ca3af;
}
@media (max-width: 480px) {
.page-wrapper {
padding: 1rem;
}
.card {
padding: 1.4rem 1.1rem 1.2rem;
border-radius: 0.9rem;
}
h2 {
font-size: 1.2rem;
}
input,
textarea {
font-size: 1.02rem;
}
button {
font-size: 1.02rem;
}
}
</style>
</head>
<body>
<div class="page-wrapper">
<div class="card">
<h2>Submit YouTube Playlist</h2>
<p class="subtitle">
Paste a playlist link below. It’ll be queued for download and assigned to the next free slot.
</p>
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for m in messages %}
<div class="flash">{{ m }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<form method="post" action="{{ url_for('submit') }}">
<div class="form-group">
<label for="url">YouTube URL</label>
<input
type="url"
id="url"
name="url"
required
placeholder="https://www.youtube.com/playlist?list=..."
>
</div>
<div class="form-group">
<label for="submitter">Your name (optional)</label>
<input
type="text"
id="submitter"
name="submitter"
placeholder="Simon Peter"
>
</div>
<div class="form-group">
<label for="note">Note (optional)</label>
<textarea
id="note"
name="note"
rows="3"
placeholder="Service, event, etc."
></textarea>
</div>
<button type="submit">Submit Playlist</button>
</form>
<p class="helper">
Playlists are kept for roughly 48 hours after they’re downloaded.
</p>
</div>
</div>
</body>
</html>
"""
@app.route("/", methods=["GET"])
def index():
return render_template_string(HTML_FORM)
@app.route("/submit", methods=["POST"])
def submit():
url = request.form.get("url", "").strip()
submitter = request.form.get("submitter", "").strip() or None
note = request.form.get("note", "").strip() or None
if not url.startswith("http"):
flash("Invalid URL.")
return redirect(url_for("index"))
result = enqueue_download(url, submitter, note)
if result.get("status") == "queue_full":
secs = result.get("oldest_expires_in_seconds", 0)
hours = max(1, secs // 3600)
flash(f"Queue is full. Oldest playlist expires in about {hours} hour(s).")
else:
slot = result.get("slot")
msg = f"Playlist queued in slot {slot}."
if result.get("reused_slot"):
msg += " (Existing slot – only new videos will be added.)"
else:
msg += " It will start downloading shortly."
flash(msg)
return redirect(url_for("index"))
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7531)))