Compare commits
6 Commits
40c516dcc8
...
8f6a42f8b4
Author | SHA1 | Date | |
---|---|---|---|
8f6a42f8b4 | |||
7fbea281b8 | |||
4064b4d9b7 | |||
8afeb618d3 | |||
ee8215e7bc | |||
d114672681 |
25
README.md
25
README.md
@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
Tools to manage an UltraStar DX song library. Features include:
|
Tools to manage an UltraStar DX song library. Features include:
|
||||||
|
|
||||||
1. Deduplication
|
1. Web-based catalogue UI
|
||||||
2. Organization
|
2. Deduplication
|
||||||
3. Recoding
|
3. Organization
|
||||||
4. Jsonification
|
4. Recoding
|
||||||
|
5. Jsonification
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
@ -23,6 +24,22 @@ We assume that your song library is stored at `$SONG_LIBRARY`. Replace this plac
|
|||||||
export SONG_LIBRARY=/path/to/library
|
export SONG_LIBRARY=/path/to/library
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Web-based catalogue UI
|
||||||
|
|
||||||
|
**A web-based UI to browse the song library.** It supports searching by title and artist, and allows to mark and unmark favorites on the client side (using local storage).
|
||||||
|
|
||||||
|
#### Serve
|
||||||
|
|
||||||
|
**Launch a server for the catalogue UI** on localhost. Mostly useful for development purposes.
|
||||||
|
|
||||||
|
ℹ️ This is completely risk-free, as it does not change files.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m karaokatalog.ui.serve $SONG_LIBRARY
|
||||||
|
```
|
||||||
|
|
||||||
|
To speed up the start, use jsonification to create and persist a JSON of all songs in the library root dir before starting this UI.
|
||||||
|
|
||||||
### Deduplication
|
### Deduplication
|
||||||
|
|
||||||
**Find and delete exactly duplicated songs**, i.e., songs with the same title and artist that also consist of exactly the same files in the directory.
|
**Find and delete exactly duplicated songs**, i.e., songs with the same title and artist that also consist of exactly the same files in the directory.
|
||||||
|
0
karaokatalog/ui/__init__.py
Normal file
0
karaokatalog/ui/__init__.py
Normal file
0
karaokatalog/ui/serve/__init__.py
Normal file
0
karaokatalog/ui/serve/__init__.py
Normal file
32
karaokatalog/ui/serve/__main__.py
Normal file
32
karaokatalog/ui/serve/__main__.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from karaokatalog.get_parser import get_parser
|
||||||
|
from karaokatalog.Library import Library
|
||||||
|
from karaokatalog.ui.serve.get_flask_app import get_flask_app
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
format="%(asctime)s [%(levelname)s] %(message)s", level=logging.INFO
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = get_parser(
|
||||||
|
"ui.serve", "Serve a web UI to browse the Karaokatalog"
|
||||||
|
).parse_args()
|
||||||
|
|
||||||
|
songs_json_path = args.library_path / "songs.json"
|
||||||
|
|
||||||
|
if songs_json_path.exists():
|
||||||
|
logging.info(f"Loading {songs_json_path}")
|
||||||
|
with songs_json_path.open("r", encoding="utf-8") as f:
|
||||||
|
songs = json.load(f)
|
||||||
|
else:
|
||||||
|
logging.info("Loading library")
|
||||||
|
library = Library.from_dir(args.library_path)
|
||||||
|
logging.info("Library loaded")
|
||||||
|
songs = [song.as_dict() for song in library.songs]
|
||||||
|
|
||||||
|
logging.info("Starting UI")
|
||||||
|
app = get_flask_app(songs)
|
||||||
|
app.run(port=5657)
|
20
karaokatalog/ui/serve/get_flask_app.py
Normal file
20
karaokatalog/ui/serve/get_flask_app.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from collections.abc import Sequence
|
||||||
|
|
||||||
|
from flask import Flask, Response
|
||||||
|
|
||||||
|
|
||||||
|
def get_flask_app(songs: Sequence[dict[str, str]]) -> Flask:
|
||||||
|
app = Flask("karaokatalog.ui", static_url_path="/")
|
||||||
|
|
||||||
|
# This is only to make the type checker happy.
|
||||||
|
songs_list = list(songs)
|
||||||
|
|
||||||
|
@app.get("/songs.json")
|
||||||
|
def get_songs() -> list[dict[str, str]]:
|
||||||
|
return songs_list
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
def get_index() -> Response:
|
||||||
|
return app.send_static_file("index.html")
|
||||||
|
|
||||||
|
return app
|
Loading…
x
Reference in New Issue
Block a user