initialize

This commit is contained in:
2022-02-06 10:19:03 +01:00
commit 75749efa02
61 changed files with 5121 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
{% extends "template.html" %}
{% block content %}
{% if error == 'play': %}
<div class="my-3 alert alert-danger">
Error on playing from card.
</div>
{% endif %}
{% endblock %}
+134
View File
@@ -0,0 +1,134 @@
{% extends "template.html" %}
{% block content %}
<h1>luniebox</h1>
<p>Welcome to luniebox web-interface. This is for configuring and control your luniebox device.</p>
<div class="row">
<div class="col col-xs-12 col-md-6 col-lg-6 col-xl-6 mt-3">
<div class="card">
<div class="card-body">
<h5 class="card-title">Daemon</h5>
<p class="card-text">
{% if daemon_error: %}
<div class="my-3 alert alert-danger">
{{ daemon_error }}
<a href="{{ url_for('api.daemon_start') }}" class="btn btn-secondary">Start daemon</a>
</div>
{% endif %}
{% if daemon_status: %}
<div class="my-3 alert alert-success">
{{ daemon_status }}
</div>
{% endif %}
</p>
</div>
</div>
<div class="card mt-3">
<div class="card-body">
<h5 class="card-title">Spotify Integration</h5>
<p class="card-text">
{% if spotify['errors']['setup']: %}
<div class="alert alert-danger" role="alert">
No luniebox device found! Please setup spotifyd propertly (device name must match name from setup, default is 'luniebox')!
</div>
{% endif %}
{% if spotify['errors']['not_running']: %}
<div class="alert alert-warning" role="alert">
Spotifyd is not running. Please start spotifyd service on your luniebox!
<a href="{{ url_for('api.restart_spotifyd') }}" class="btn btn-primary">Restart spotifyd</a>
</div>
{% endif %}
{% if spotify['status']['not_active']: %}
<div class="alert alert-success" role="alert">
Spotify is available but currently inactive.
</div>
{% endif %}
<table class="table">
<tbody>
{% if spotify['status']['device']: %}
<tr class="{{ 'table-success' if spotify['status']['device']['id'] == spotify['device_id'] else '' }}">
<th scope="row">Current Device</th>
<td>{{ spotify['status']['device']['name'] }}</td>
</tr>
{% endif %}
{% if spotify['status']['item']: %}
{% with item = spotify['status']['item'] %}
<tr class="{{ '' if spotify['status']['is_playing'] else 'table-active' }}">
<th>{{ 'Currently playing' if spotify['status']['is_playing'] else 'Last played' }}</th>
<td class="d-flex w-100">
{% include "spotify/items/track.html" %}
</td>
</tr>
{% endwith %}
{% endif %}
</tbody>
</table>
</p>
</div>
</div>
<div class="card mt-3">
<div class="card-body">
<h5 class="card-title">Music Player Daemon Integration</h5>
<p class="card-text">
{% if not mpd: %}
<div class="my-3 alert alert-danger">
Music Player Daemon not connected
<a href="{{ url_for('api.restart_mpd') }}" class="btn btn-primary">Restart mpd</a>
</div>
{% endif %}
{% if mpd: %}
<table class="table">
<tbody>
<tr class="table-success">
<th scope="row">Current state</th>
<td>{{ mpd['state'] }}</td>
</tr>
{% if mpd['song']: %}
{% with item = mpd['song'] %}
<tr class="{{ '' if mpd['state'] == 'play' else 'table-active' }}">
<th>{{ 'Currently playing' if mpd['state'] == 'play' else 'Last played' }}</th>
<td class="d-flex w-100">
<div class="d-flex flex-column flex-grow-1">
<h5 class="mb-1">{{ item['title'] }}</h5>
<p class="mb-1">
{{ item['artist'] }}
</p>
<small class="text-muted">{{ item['album'] }}</small>
</div>
</td>
</tr>
{% endwith %}
{% endif %}
</tbody>
</table>
{% endif %}
</p>
</div>
</div>
</div>
<div class="col col-xs-12 col-md-6 col-lg-6 col-xl-6 mt-3">
<div class="card">
<div class="card-body">
<p class="alert alert-warning">This will stop daemon. You need to restart daemon afterwards!</p>
<a href="{{ url_for('api.rfid_read') }}" class="btn btn-primary">Read card</a>
<a href="{{ url_for('api.rfid_play') }}" class="btn btn-secondary">Play card</a>
</div>
</div>
</div>
</div>
{% endblock %}
+50
View File
@@ -0,0 +1,50 @@
{% extends "template.html" %}
{% block content %}
<div class="mpd-search-results">
<div class="container">
{% if path: %}
<h3>{{ path }}</h3>
{% endif %}
<div class="d-flex flex-column mt-3">
<ul class="list-group mb-3 flex-fill">
{% for item in results %}
{% if item.directory and (spotify and item.directory.startswith('spotify:') or not spotify and not item.directory.startswith('spotify:')): %}
<li href="#" class="list-group-item flex-fill">
<div class="d-flex w-100">
<h5 class="mb-1"><a href="{{ url_for('pages.mpd_list', path=item.directory) }}">{{ item.directory }}</a>
</h5>
</div>
<a class="btn btn-primary" href="{{ url_for('api.rfid_write', value='mpd:' + item.directory) }}"><i
class="bi bi-pencil-square"></i>
Write to card</a>
<a class="btn btn-secondary" href="{{ url_for('api.play', uri='mpd:' + item.directory) }}"><i
class="bi bi-play"></i> Play
now</a>
{% endif %}
</li>
{% if item.file and not item.file.startswith('.') and (spotify and item.file.startswith('spotify:') or not spotify and not item.file.startswith('spotify:')): %}
<li href="#" class="list-group-item flex-fill">
<div class="d-flex w-100">
<h5 class="mb-1">{{ item.file }}</h5>
</div>
<a class="btn btn-primary" href="{{ url_for('api.rfid_write', value='mpd:' + path + '/' + item.file) }}"><i
class="bi bi-pencil-square"></i>
Write to card</a>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
{% if not spotify: %}
<a href="{{ url_for('pages.mpd_list', spotify=true) }}">List Spotify Downloads</a>
{% endif %}
{% if spotify: %}
<a href="{{ url_for('pages.mpd_list') }}">List MPD files</a>
{% endif %}
</div>
</div>
{% endblock %}
+60
View File
@@ -0,0 +1,60 @@
{% extends "template.html" %}
{% block content %}
<h1> Setup </h1>
<p>Here you can setup the luniebox or restart services when having issues.</p>
<div class="row">
{% if model['setup']: %}
<div class="col col-xs-12 col-md-6 col-lg-6 col-xl-6 mt-3">
<div class="card">
<div class="card-body">
<a href="{{ url_for('api.restart_spotifyd') }}" class="btn btn-primary">Restart spotifyd</a>
<a href="{{ url_for('api.daemon_start') }}" class="btn btn-secondary">Start daemon</a>
<a href="{{ url_for('api.daemon_stop') }}" class="btn btn-warning">Stop daemon</a>
</div>
</div>
</div>
{% endif %}
<div class="col col-xs-12 col-md-6 col-lg-6 col-xl-6 mt-3">
{% if model['setup']: %}
<div class="my-3 alert alert-warning">
Already set-up! On changes you may need to restart spotifyd service.
</div>
{% endif %}
<form method="POST" action="{{ url_for('api.setup') }}">
<div class="mb-3">
<label for="spotify-device-name" class="form-label">Spotify Device Name</label>
<input type="text" class="form-control" id="spotify-device-name" name="spotify-device-name" required
value="{{'' if not model['device-name'] else '' + model['device-name'] }}">
</div>
<div class="mb-3">
<label for="spotify-username" class="form-label">Spotify Username</label>
<input type="text" class="form-control" id="spotify-username" name="spotify-username" required
value="{{'' if not model['username'] else '' + model['username'] }}">
</div>
<div class="mb-3">
<label for="spotify-password" class="form-label">Spotify Password</label>
<input type="password" class="form-control" id="spotify-password" name="spotify-password" required
value="{{'' if not model['password'] else '' + model['password'] }}">
</div>
<div class="mb-3">
<label for="spotify-client-id" class="form-label">Spotify Client Id</label>
<input type="text" class="form-control" id="spotify-client-id" name="spotify-client-id" required
value="{{'' if not model['client-id'] else '' + model['client-id'] }}">
</div>
<div class="mb-3">
<label for="spotify-client-secret" class="form-label">Spotify Client Secret</label>
<input type="text" class="form-control" id="spotify-client-secret" name="spotify-client-secret" required
value="{{'' if not model['client-secret'] else '' + model['client-secret'] }}">
</div>
<div class="mb-3">
<label for="spotify-redirect-uri" class="form-label">Spotify Redirect Uri</label>
<input type="text" class="form-control" id="spotify-redirect-uri" name="spotify-redirect-uri"
value="{{'' if not model['redirect-uri'] else '' + model['redirect-uri'] }}">
</div>
<button type="submit" class="btn btn-primary">Setup</button>
</form>
</div>
</div>
{% endblock %}
@@ -0,0 +1,11 @@
<div class="d-flex flex-column flex-grow-1">
<h5 class="mb-1">{{ item['name'] }}</h5>
<p class="mb-1">
{{ item['artists'] | map(attribute='name') | join(', ') }}
</p>
<small class="text-muted"></small>
</div>
{%if item['images']: %}
{% set images = item['images'] %}
{% include "spotify/items/cover.html" %}
{% endif %}
@@ -0,0 +1,9 @@
<div class="d-flex flex-column flex-grow-1">
<h5 class="mb-1">{{ item['name'] }}</h5>
<p class="mb-1"></p>
<small class="text-muted"></small>
</div>
{%if item['images']: %}
{% set images = item['images'] %}
{% include "spotify/items/cover.html" %}
{% endif %}
@@ -0,0 +1,11 @@
<div class="dropdown">
<img src="{{ images | map(attribute='url') | first }}" class="item-image rounded dropdown-toggle"
data-bs-toggle="dropdown" data-bs-placement="top" title="Download Cover">
<ul class="dropdown-menu">
{% for image in images %}
<li>
<a class="dropdown-item" href="{{image['url']}}" target="_blank">{{image['width']}}px</a>
</li>
{% endfor %}
</ul>
</div>
@@ -0,0 +1,9 @@
<div class="d-flex flex-column flex-grow-1">
<h5 class="mb-1">{{ item['name'] }}</h5>
<p class="mb-1"></p>
<small class="text-muted"></small>
</div>
{%if item['images']: %}
{% set images = item['images'] %}
{% include "spotify/items/cover.html" %}
{% endif %}
@@ -0,0 +1,22 @@
<div class="d-flex w-100 mt-3 justify-content-between">
<a class="btn btn-primary" href="{{ url_for('api.rfid_write', value=item.uri) }}"><i class="bi bi-pencil-square"></i>
Write to card</a>
<a class="btn btn-secondary" href="{{ url_for('api.play', uri=item.uri) }}"><i class="bi bi-play"></i> Play
now</a>
{% if 'spotifydl' in item: %}
{% if item['spotifydl'] == 'SpotifyDLStatus.NONE': %}
<a class="btn btn-warning" href="{{ url_for('api.spotify_dl', uri=item.uri) }}"><i class="bi bi-save"></i>
Download</a>
{% else: %}
<p>
{% if item['spotifydl'] == 'SpotifyDLStatus.FINISHED': %}
<span class="badge rounded-pill bg-success">Downloaded</span>
{% elif item['spotifydl'] == 'SpotifyDLStatus.RUNNING': %}
<span class="badge rounded-pill bg-info">Running</span>
{% elif item['spotifydl'] == 'SpotifyDLStatus.ERROR': %}
<span class="badge rounded-pill bg-danger">Error</span>
{% endif %}
</p>
{% endif %}
{% endif %}
</div>
@@ -0,0 +1,11 @@
<div class="d-flex flex-column flex-grow-1">
<h5 class="mb-1">{{ item['name'] }}</h5>
<p class="mb-1">
{{ item['description'] }}
</p>
<small class="text-muted"></small>
</div>
{%if item['images']: %}
{% set images = item['images'] %}
{% include "spotify/items/cover.html" %}
{% endif %}
@@ -0,0 +1,9 @@
<div class="d-flex flex-column flex-grow-1">
<h5 class="mb-1">{{ item['name'] }}</h5>
<p class="mb-1"></p>
<small class="text-muted"></small>
</div>
{%if item['images']: %}
{% set images = item['images'] %}
{% include "spotify/items/cover.html" %}
{% endif %}
@@ -0,0 +1,11 @@
<div class="d-flex flex-column flex-grow-1">
<h5 class="mb-1">{{ item['name'] }}</h5>
<p class="mb-1">
{{ item['artists'] | map(attribute='name') | join(', ') }}
</p>
<small class="text-muted">{{ item['album']['name'] }}</small>
</div>
{%if item['album']['images']: %}
{% set images = item['album']['images'] %}
{% include "spotify/items/cover.html" %}
{% endif %}
+117
View File
@@ -0,0 +1,117 @@
{% extends "template.html" %}
{% block content %}
<div class="mt-3">
<form method="GET" action="{{ url_for('pages.spotify_search') }}">
<div class="mb-3">
<label for="search-query" class="form-label">Search</label>
<input type="text" name="q" id="search-query" class="form-control" placeholder="Artists, songs, or podcasts"
required value="{{ query }}">
</div>
<div class="mb-3">
<div class="row">
<div class="col">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="type" value="track" id="search-type-track" {{'checked'
if 'track' in types else '' }}>
<label class="form-check-label" for="search-type-track">
Tracks
</label>
</div>
</div>
<div class="col">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="type" value="album" id="search-type-album" {{'checked'
if 'album' in types else '' }}>
<label class="form-check-label" for="search-type-album">
Albums
</label>
</div>
</div>
<div class="col">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="type" value="artist" id="search-type-artist"
{{'checked' if 'artist' in types else '' }}>
<label class="form-check-label" for="search-type-artist">
Artists
</label>
</div>
</div>
<div class="col">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="type" value="playlist" id="search-type-playlist"
{{'checked' if 'playlist' in types else '' }}>
<label class="form-check-label" for="search-type-playlist">
Playlists
</label>
</div>
</div>
<div class="col">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="type" value="show" id="search-type-show" {{'checked'
if 'show' in types else '' }}>
<label class="form-check-label" for="search-type-show">
Shows
</label>
</div>
</div>
<div class="col">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="type" value="episode" id="search-type-episode"
{{'checked' if 'episode' in types else '' }}>
<label class="form-check-label" for="search-type-episode">
Episodes
</label>
</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Search</button>
</form>
</div>
{% if results: %}
<div class="alert alert-warning mt-3">
Writing to card will stop the daemon. You need to restart daemon afterwards!
</div>
<div class="spotify-search-results">
<div class="container">
<div class="row">
{% for type in types %}
{% if results[type + 's']: %}
{% with result = results[type + 's'] %}
<div
class="d-flex flex-column col col-xs-12 col-md-6 col-lg-6 {{ 'col-xl-4' if results|length > 2 else 'col-xl-6' }} mt-3">
<h3>{{ type | capitalize}}s</h3>
<ul class="list-group mb-3 flex-fill">
{% for item in result['items'] %}
<li href="#" class="list-group-item flex-fill">
<div class="d-flex w-100">
{% include "spotify/items/" + type + ".html" %}
</div>
{% include "spotify/items/menu.html" %}
</li>
{% endfor %}
</ul>
<div class="d-flex w-100 justify-content-between mt-auto">
<a href="{{ url_for('pages.spotify_search',q=query, type=type, limit=result['limit'], offset=result['offset']-result['limit']) }}"
class="btn btn-primary {{ 'disabled' if result['offset']==0 else '' }} " {{ 'disabled' if
result['offset']==0 else '' }}>&laquo;</a>
<a href="{{ url_for('pages.spotify_search',q=query, type=type, limit=result['limit'], offset=result['offset']+result['limit']) }}"
{{ 'disabled' if result['offset']>= result['total'] else ''}}
class="btn btn-primary {{ 'disabled' if result['offset']>= result['total'] else ''}}">&raquo;</a>
</div>
</div>
{% endwith %}
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endif %}
{% endblock %}
+10
View File
@@ -0,0 +1,10 @@
{% extends "template.html" %}
{% block content %}
{% if uri: %}
<h3>{{ uri }}</h3>
{% endif %}
<p>{{ status }}</p>
{% endblock %}
+60
View File
@@ -0,0 +1,60 @@
{% extends "template.html" %}
{% block content %}
{% if success['rfid_write']: %}
<div class="my-3 alert alert-success">
Write card value: {{ success['rfid_write'] }}
</div>
{% endif %}
{% if success['rfid_read']: %}
<div class="my-3 alert alert-success">
Read card value: {{ success['rfid_read'] }}
</div>
{% endif %}
{% if success['rfid_play']: %}
<div class="my-3 alert alert-success">
Start playing from card.
</div>
{% endif %}
{% if success['play']: %}
<div class="my-3 alert alert-success">
Start playing {{ success['play'] }}.
</div>
{% endif %}
{% if success['restart_spotifyd']: %}
<div class="my-3 alert alert-secondary">
Restartet spotifyd service.
</div>
{% endif %}
{% if success['restart_mpd']: %}
<div class="my-3 alert alert-secondary">
Restartet mpd service.
</div>
{% endif %}
{% if success['start_daemon']: %}
<div class="my-3 alert alert-success">
Started luniebox-daemon service.
</div>
{% endif %}
{% if success['stop_daemon']: %}
<div class="my-3 alert alert-warning">
Stopped luniebox-daemon service.
</div>
{% endif %}
{% if success['restart_luniebox']: %}
<div class="my-3 alert alert-secondary">
Restartet luniebox-app service.
</div>
{% endif %}
<a class="btn btn-primary" href="{{ url_for('pages.index') }}">Go back to status page</a>
{% endblock %}
+52
View File
@@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>luniebox</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-icons.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<header>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="{{ url_for('pages.index') }}">luniebox</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{{ url_for('pages.index') }}">Status</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{{ url_for('pages.spotify_search') }}">Search Spotify</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{{ url_for('pages.mpd_list') }}">MPD listing</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{{ url_for('pages.setup') }}">Setup</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container mt-3">
{% block content %}
{% endblock %}
</div>
<footer class="mt-5">
</footer>
<script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
</body>
</html>