Added support for other providers
This commit is contained in:
parent
0b52a04e50
commit
0ff466649a
1 changed files with 217 additions and 201 deletions
|
@ -7,23 +7,39 @@ import re
|
||||||
|
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
app.config['LYRICS_DIR'] = 'lyrics'
|
app.config['LYRICS_DIR'] = 'lyrics'
|
||||||
|
|
||||||
code = ""
|
code = ""
|
||||||
history = []
|
history = []
|
||||||
|
|
||||||
|
def is_youtube_url(url):
|
||||||
|
yt_patterns = [
|
||||||
|
r'youtube\.com/watch\?v=',
|
||||||
|
r'music\.youtube\.com/watch\?v=',
|
||||||
|
r'youtu\.be/'
|
||||||
|
]
|
||||||
|
return any(re.search(pattern, url) for pattern in yt_patterns)
|
||||||
|
|
||||||
|
def extract_yt_id(url):
|
||||||
|
patterns = [
|
||||||
|
r'v=([a-zA-Z0-9_-]{11})',
|
||||||
|
r'youtu\.be/([a-zA-Z0-9_-]{11})',
|
||||||
|
r'/([a-zA-Z0-9_-]{11})$'
|
||||||
|
]
|
||||||
|
for pattern in patterns:
|
||||||
|
match = re.search(pattern, url)
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
return None
|
||||||
|
|
||||||
@app.route('/musicstatus.html', methods=['GET', 'POST'])
|
@app.route('/musicstatus.html', methods=['GET', 'POST'])
|
||||||
def musicstatus():
|
def musicstatus():
|
||||||
global code, history
|
global code, history
|
||||||
|
|
||||||
# POST Request Handling
|
|
||||||
if flask.request.method == 'POST':
|
if flask.request.method == 'POST':
|
||||||
data = flask.request.get_json()
|
data = flask.request.get_json()
|
||||||
|
|
||||||
# Validate verification code
|
|
||||||
if code != data.get('verificationcode'):
|
if code != data.get('verificationcode'):
|
||||||
return "Verification failed", 403
|
return "Verification failed", 403
|
||||||
|
|
||||||
# Create new entry
|
|
||||||
entry = (
|
entry = (
|
||||||
data['music'],
|
data['music'],
|
||||||
data['time'],
|
data['time'],
|
||||||
|
@ -31,19 +47,15 @@ def musicstatus():
|
||||||
data['videoid']
|
data['videoid']
|
||||||
)
|
)
|
||||||
|
|
||||||
# Handle history reset
|
|
||||||
if data.get('resetstatus', '').lower() == "true":
|
if data.get('resetstatus', '').lower() == "true":
|
||||||
history.clear()
|
history.clear()
|
||||||
|
|
||||||
history.append(entry)
|
history.append(entry)
|
||||||
return "Entry added successfully"
|
return "Entry added successfully"
|
||||||
|
|
||||||
# GET Request Handling
|
|
||||||
elif flask.request.method == 'GET':
|
|
||||||
current_playing = history[-1] if history else None
|
current_playing = history[-1] if history else None
|
||||||
lyrics_content = []
|
lyrics_content = []
|
||||||
|
|
||||||
# Load lyrics if available
|
|
||||||
if current_playing:
|
if current_playing:
|
||||||
lrc_path = os.path.join(app.config['LYRICS_DIR'], f"{current_playing[0]}.lrc")
|
lrc_path = os.path.join(app.config['LYRICS_DIR'], f"{current_playing[0]}.lrc")
|
||||||
if os.path.exists(lrc_path):
|
if os.path.exists(lrc_path):
|
||||||
|
@ -73,13 +85,11 @@ def musicstatus():
|
||||||
--text-color: #ffffff;
|
--text-color: #ffffff;
|
||||||
--font-family: 'JetBrains Mono', monospace;
|
--font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.music-card {
|
.music-card {
|
||||||
background: var(--card-bg);
|
background: var(--card-bg);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
@ -89,7 +99,6 @@ def musicstatus():
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbnail {
|
.thumbnail {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
@ -97,7 +106,6 @@ def musicstatus():
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 2px solid var(--border-color);
|
border: 2px solid var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.play-button {
|
.play-button {
|
||||||
background: #333;
|
background: #333;
|
||||||
border: 1px solid #444;
|
border: 1px solid #444;
|
||||||
|
@ -110,21 +118,17 @@ def musicstatus():
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-table {
|
.history-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
.history-table th, .history-table td {
|
||||||
.history-table th,
|
|
||||||
.history-table td {
|
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
padding: 0.8rem;
|
padding: 0.8rem;
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lyrics-container {
|
.lyrics-container {
|
||||||
background: #333;
|
background: #333;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
@ -132,12 +136,10 @@ def musicstatus():
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lyrics-line {
|
.lyrics-line {
|
||||||
margin: 0.5rem 0;
|
margin: 0.5rem 0;
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.music-card {
|
.music-card {
|
||||||
grid-template-columns: 200px 1fr;
|
grid-template-columns: 200px 1fr;
|
||||||
|
@ -158,23 +160,38 @@ def musicstatus():
|
||||||
|
|
||||||
{% if current_playing %}
|
{% if current_playing %}
|
||||||
<div class="music-card">
|
<div class="music-card">
|
||||||
<img src="https://img.youtube.com/vi/{{ current_playing[3] }}/hqdefault.jpg"
|
{% if is_youtube(current_playing[3]) %}
|
||||||
|
<img src="https://img.youtube.com/vi/{{ extract_yt_id(current_playing[3]) }}/hqdefault.jpg"
|
||||||
class="thumbnail"
|
class="thumbnail"
|
||||||
alt="{{ current_playing[0] }} cover">
|
alt="{{ current_playing[0] }} cover">
|
||||||
|
{% else %}
|
||||||
|
<div class="thumbnail" style="background: #333; display: flex; align-items: center; justify-content: center;">
|
||||||
|
<span style="color: #666;">No thumbnail available</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2>{{ current_playing[0] }}</h2>
|
<h2>{{ current_playing[0] }}</h2>
|
||||||
<p>🕒 Last Updated: {{ format_timestamp(current_playing[1]) }}</p>
|
<p>🕒 Last Updated: {{ format_timestamp(current_playing[1]) }}</p>
|
||||||
<div>
|
<div>
|
||||||
<a href="https://www.youtube.com/watch?v={{ current_playing[3] }}"
|
{% if is_youtube(current_playing[3]) %}
|
||||||
|
<a href="https://www.youtube.com/watch?v={{ extract_yt_id(current_playing[3]) }}"
|
||||||
class="play-button"
|
class="play-button"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
▶ YouTube
|
▶ YouTube
|
||||||
</a>
|
</a>
|
||||||
<a href="https://music.youtube.com/watch?v={{ current_playing[3] }}"
|
<a href="https://music.youtube.com/watch?v={{ extract_yt_id(current_playing[3]) }}"
|
||||||
class="play-button"
|
class="play-button"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
▶ YT Music
|
▶ YT Music
|
||||||
</a>
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ current_playing[3] }}"
|
||||||
|
class="play-button"
|
||||||
|
target="_blank">
|
||||||
|
▶ Play Source
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if lyrics_content %}
|
{% if lyrics_content %}
|
||||||
<div class="lyrics-container">
|
<div class="lyrics-container">
|
||||||
|
@ -206,14 +223,20 @@ def musicstatus():
|
||||||
{% for entry in history|reverse %}
|
{% for entry in history|reverse %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<img src="https://img.youtube.com/vi/{{ entry[3] }}/hqdefault.jpg"
|
{% if is_youtube(entry[3]) %}
|
||||||
|
<img src="https://img.youtube.com/vi/{{ extract_yt_id(entry[3]) }}/hqdefault.jpg"
|
||||||
style="width: 80px; border-radius: 4px;"
|
style="width: 80px; border-radius: 4px;"
|
||||||
alt="{{ entry[0] }} thumbnail">
|
alt="{{ entry[0] }} thumbnail">
|
||||||
|
{% else %}
|
||||||
|
<div style="width: 80px; height: 45px; background: #333; border-radius: 4px; display: flex; align-items: center; justify-content: center;">
|
||||||
|
<span style="color: #666;">N/A</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ entry[0] }}</td>
|
<td>{{ entry[0] }}</td>
|
||||||
<td>{{ format_timestamp(entry[1]) }}</td>
|
<td>{{ format_timestamp(entry[1]) }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="https://www.youtube.com/watch?v={{ entry[3] }}"
|
<a href="{{ entry[3] }}"
|
||||||
class="play-button"
|
class="play-button"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
▶
|
▶
|
||||||
|
@ -228,15 +251,11 @@ def musicstatus():
|
||||||
</html>
|
</html>
|
||||||
''', current_playing=current_playing,
|
''', current_playing=current_playing,
|
||||||
history=history,
|
history=history,
|
||||||
format_timestamp=format_timestamp,
|
format_timestamp=lambda ts: datetime.datetime.fromtimestamp(int(ts), datetime.timezone.utc).strftime("%Y-%m-%d %H:%M UTC"),
|
||||||
|
is_youtube=is_youtube_url,
|
||||||
|
extract_yt_id=extract_yt_id,
|
||||||
lyrics_content=lyrics_content)
|
lyrics_content=lyrics_content)
|
||||||
|
|
||||||
def format_timestamp(timestamp):
|
|
||||||
return datetime.datetime.fromtimestamp(
|
|
||||||
int(timestamp),
|
|
||||||
datetime.timezone.utc
|
|
||||||
).strftime("%Y-%m-%d %H:%M UTC")
|
|
||||||
|
|
||||||
@app.route('/verifykey', methods=['POST'])
|
@app.route('/verifykey', methods=['POST'])
|
||||||
def verifycert():
|
def verifycert():
|
||||||
global code
|
global code
|
||||||
|
@ -249,9 +268,6 @@ def verifycert():
|
||||||
|
|
||||||
@app.route('/<path:path>')
|
@app.route('/<path:path>')
|
||||||
def catch_all(path):
|
def catch_all(path):
|
||||||
if path == None:
|
|
||||||
return flask.redirect('https://halhadus.rocks')
|
|
||||||
if not path == 'musicstatus.html' or not path == 'verifykey':
|
|
||||||
return flask.redirect(f'https://halhadus.rocks/{path}')
|
return flask.redirect(f'https://halhadus.rocks/{path}')
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
|
@ -260,5 +276,5 @@ def index():
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if not os.path.exists(app.config['LYRICS_DIR']):
|
if not os.path.exists(app.config['LYRICS_DIR']):
|
||||||
os.makedirs(app.config['LYRICS_DIR'])
|
os.makedirs(app.config['LYRICS_DIR'], exist_ok=True)
|
||||||
app.run(host='0.0.0.0', port=int(os.environ.get('PORT')))
|
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
|
||||||
|
|
Loading…
Add table
Reference in a new issue