diff --git a/.env.example b/.env.example index 20939df..c782e16 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,18 @@ -PLEX_TOKEN=replace-with-your-plex-token -SERVER_IP=192.168.1.100 -PLAYLIST_NAME=Journey FM Recently Played +PLEX_TOKEN=pU-m3HWYUZU6iXJFhJyA +SERVER_IP=172.16.16.106 +PLAYLIST_NAME=Radio SELECTED_STATIONS=journey_fm,spirit_fm,klove AUTO_UPDATE=true UPDATE_INTERVAL=15 UPDATE_UNIT=Minutes CONTAINER_RUN_MODE=loop +ENABLE_WEB_DASHBOARD=true +DASHBOARD_PORT=8765 +JOURNEYFM_DATA_DIR=/data +CHROME_BINARY=/usr/bin/chromium +CHROMEDRIVER_PATH=/usr/bin/chromedriver +JOURNEYFM_CONTAINER=1 +PYTHONUNBUFFERED=1 +PYTHONDONTWRITEBYTECODE=1 +LANG=C.UTF-8 +TERM=xterm diff --git a/README.md b/README.md index a694bcc..8b5af64 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,31 @@ Quick setup: ./install.sh ``` +Interactive install now captures defaults and writes `.env` (auto with optional values): + +```bash +./install.sh +``` + +The installer sets defaults: +- UPDATE_UNIT=Minutes +- CONTAINER_RUN_MODE=loop +- SERVER_IP=172.16.16.106 +- PLAYLIST_NAME=Radio +- SELECTED_STATIONS=journey_fm,spirit_fm,klove +- UPDATE_INTERVAL=15 +- AUTO_UPDATE=true +- PLEX_TOKEN=pU-m3HWYUZU6iXJFhJyA +- PYTHONUNBUFFERED=1 +- JOURNEYFM_DATA_DIR=/data +- TERM=xterm +- CHROME_BINARY=/usr/bin/chromium +- JOURNEYFM_CONTAINER=1 +- LANG=C.UTF-8 +- CHROMEDRIVER_PATH=/usr/bin/chromedriver + +Web dashboard defaults to enabled with start at http://localhost:8765 (or `DASHBOARD_PORT`). + Manual setup: ```bash diff --git a/docker-compose.yml b/docker-compose.yml index 11288ef..6c55d01 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,18 +5,27 @@ services: dockerfile: Dockerfile container_name: journey-fm-playlist restart: unless-stopped + ports: + - "8765:8765" environment: PLEX_TOKEN: ${PLEX_TOKEN} SERVER_IP: ${SERVER_IP} PLAYLIST_NAME: ${PLAYLIST_NAME:-Journey FM Recently Played} - SELECTED_STATIONS: ${SELECTED_STATIONS:-journey_fm,spirit_fm} + SELECTED_STATIONS: ${SELECTED_STATIONS:-journey_fm,spirit_fm,klove} AUTO_UPDATE: ${AUTO_UPDATE:-true} UPDATE_INTERVAL: ${UPDATE_INTERVAL:-15} UPDATE_UNIT: ${UPDATE_UNIT:-Minutes} CONTAINER_RUN_MODE: ${CONTAINER_RUN_MODE:-loop} + ENABLE_WEB_DASHBOARD: ${ENABLE_WEB_DASHBOARD:-true} + DASHBOARD_PORT: ${DASHBOARD_PORT:-8765} CHROME_BINARY: /usr/bin/chromium CHROMEDRIVER_PATH: /usr/bin/chromedriver JOURNEYFM_DATA_DIR: /data + JOURNEYFM_CONTAINER: 1 + PYTHONUNBUFFERED: 1 + PYTHONDONTWRITEBYTECODE: 1 + LANG: C.UTF-8 + TERM: xterm volumes: - journey-fm-data:/data diff --git a/install.sh b/install.sh index ae10cfb..194c135 100755 --- a/install.sh +++ b/install.sh @@ -1,6 +1,8 @@ #!/bin/bash # Journey FM Playlist Creator - Linux Installer +set -e + echo "Journey FM Playlist Creator - Linux Installer" echo "==============================================" @@ -9,6 +11,82 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" echo "Installing in: $DIR" +# Default configuration values +DEFAULT_PLEX_TOKEN="pU-m3HWYUZU6iXJFhJyA" +DEFAULT_SERVER_IP="172.16.16.106" +DEFAULT_PLAYLIST_NAME="Radio" +DEFAULT_SELECTED_STATIONS="journey_fm,spirit_fm,klove" +DEFAULT_AUTO_UPDATE="true" +DEFAULT_UPDATE_INTERVAL="15" +DEFAULT_UPDATE_UNIT="Minutes" +DEFAULT_CONTAINER_RUN_MODE="loop" +DEFAULT_ENABLE_WEB_DASHBOARD="true" +DEFAULT_DASHBOARD_PORT="8765" +DEFAULT_JOURNEYFM_DATA_DIR="/data" +DEFAULT_CHROME_BINARY="/usr/bin/chromium" +DEFAULT_CHROMEDRIVER_PATH="/usr/bin/chromedriver" +DEFAULT_JOURNEYFM_CONTAINER="1" +DEFAULT_PYTHONUNBUFFERED="1" +DEFAULT_PYTHONDONTWRITEBYTECODE="1" +DEFAULT_LANG="C.UTF-8" +DEFAULT_TERM="xterm" + +# Helper for interactive prompts +ask_value() { + local prompt="$1" + local default="$2" + local var + read -p "$prompt [$default]: " var + if [ -z "$var" ]; then + var="$default" + fi + echo "$var" +} + +echo "Configuring environment for .env file (press Enter to accept defaults)." + +PLEX_TOKEN=$(ask_value "Plex token" "$DEFAULT_PLEX_TOKEN") +SERVER_IP=$(ask_value "Plex server IP" "$DEFAULT_SERVER_IP") +PLAYLIST_NAME=$(ask_value "Playlist name" "$DEFAULT_PLAYLIST_NAME") +SELECTED_STATIONS=$(ask_value "Selected stations" "$DEFAULT_SELECTED_STATIONS") +AUTO_UPDATE=$(ask_value "Auto update" "$DEFAULT_AUTO_UPDATE") +UPDATE_INTERVAL=$(ask_value "Update interval" "$DEFAULT_UPDATE_INTERVAL") +UPDATE_UNIT=$(ask_value "Update unit (Minutes/Hours)" "$DEFAULT_UPDATE_UNIT") +CONTAINER_RUN_MODE=$(ask_value "Container run mode (loop/once)" "$DEFAULT_CONTAINER_RUN_MODE") +ENABLE_WEB_DASHBOARD=$(ask_value "Enable web dashboard" "$DEFAULT_ENABLE_WEB_DASHBOARD") +DASHBOARD_PORT=$(ask_value "Dashboard port" "$DEFAULT_DASHBOARD_PORT") +JOURNEYFM_DATA_DIR=$(ask_value "Data volume path" "$DEFAULT_JOURNEYFM_DATA_DIR") +CHROME_BINARY=$(ask_value "Chrome binary path" "$DEFAULT_CHROME_BINARY") +CHROMEDRIVER_PATH=$(ask_value "Chromedriver path" "$DEFAULT_CHROMEDRIVER_PATH") + +cat > "$DIR/.env" << EOF +PLEX_TOKEN=$PLEX_TOKEN +SERVER_IP=$SERVER_IP +PLAYLIST_NAME=$PLAYLIST_NAME +SELECTED_STATIONS=$SELECTED_STATIONS +AUTO_UPDATE=$AUTO_UPDATE +UPDATE_INTERVAL=$UPDATE_INTERVAL +UPDATE_UNIT=$UPDATE_UNIT +CONTAINER_RUN_MODE=$CONTAINER_RUN_MODE +ENABLE_WEB_DASHBOARD=$ENABLE_WEB_DASHBOARD +DASHBOARD_PORT=$DASHBOARD_PORT +JOURNEYFM_DATA_DIR=$JOURNEYFM_DATA_DIR +CHROME_BINARY=$CHROME_BINARY +CHROMEDRIVER_PATH=$CHROMEDRIVER_PATH +JOURNEYFM_CONTAINER=$DEFAULT_JOURNEYFM_CONTAINER +PYTHONUNBUFFERED=$DEFAULT_PYTHONUNBUFFERED +PYTHONDONTWRITEBYTECODE=$DEFAULT_PYTHONDONTWRITEBYTECODE +LANG=$DEFAULT_LANG +TERM=$DEFAULT_TERM +EOF + +echo ".env file created at $DIR/.env" + +# Ensure Docker compose exists +if ! command -v docker-compose > /dev/null 2>&1 && ! command -v docker > /dev/null 2>&1; then + echo "docker-compose/docker not found. install docker and docker-compose before running container mode." >&2 +fi + # Check if Python 3 is installed if ! command -v python3 > /dev/null 2>&1; then echo "Python 3 not found. Installing Python 3..." @@ -26,8 +104,8 @@ source "$DIR/.venv/bin/activate" echo "Installing Python dependencies..." pip install -r "$DIR/requirements.txt" -# Install Chromium browser -if ! command -v chromium-browser > /dev/null 2>&1; then +# Install Chromium browser if not available +if ! command -v chromium-browser > /dev/null 2>&1 && ! command -v chromium > /dev/null 2>&1; then echo "Installing Chromium browser..." sudo apt update && sudo apt install -y chromium-browser fi @@ -49,11 +127,13 @@ chmod +x ~/.local/share/applications/journey-fm.desktop # Update desktop database echo "Updating desktop database..." -update-desktop-database ~/.local/share/applications +update-desktop-database ~/.local/share/applications || true # Make scripts executable chmod +x "$DIR/journey_fm_app.sh" +# Optionally start web dashboard and/or app echo "Installation complete!" -echo "You can now find 'Journey FM Playlist' in your applications menu." -echo "Or run: $DIR/journey_fm_app.sh" \ No newline at end of file +echo "Run with Docker compose (server at http://localhost:$DASHBOARD_PORT):" +echo " docker compose up -d" +echo "To start GUI app: $DIR/journey_fm_app.sh" diff --git a/run_container.py b/run_container.py index 7bae766..608f5ec 100644 --- a/run_container.py +++ b/run_container.py @@ -4,6 +4,7 @@ import time from journeyfm.config_store import load_runtime_config from journeyfm.update_service import format_result_summary, run_update_job +from journeyfm.web_service import start_dashboard_server logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) @@ -23,6 +24,13 @@ def get_sleep_seconds(): def main(): os.environ.setdefault("JOURNEYFM_CONTAINER", "1") + + # Start the optional local web dashboard by default in container mode + web_mode = os.getenv("ENABLE_WEB_DASHBOARD", "true").strip().lower() + if web_mode not in ("false", "0", "no", "off"): + start_dashboard_server(host="0.0.0.0", port=int(os.getenv("DASHBOARD_PORT", "8765")), open_browser_if_possible=False) + logger.info("Started local web dashboard on port %s", os.getenv("DASHBOARD_PORT", "8765")) + run_mode = os.getenv("CONTAINER_RUN_MODE", "loop").strip().lower() while True: result = run_update_job(load_runtime_config())