diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..1af3121 --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,167 @@ +name: πŸš€ Build and Publish RetroIPTVGuide to GHCR and Docker Hub + +on: + push: + branches: [ main ] + tags: + - 'v*' + workflow_dispatch: + schedule: + - cron: '0 3 * * 0' # weekly cleanup on Sundays 03:00 UTC + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + id-token: write + + steps: + - name: 🧾 Checkout repository + uses: actions/checkout@v4 + + - name: πŸ”‘ Normalize image name to lowercase + id: prep + run: | + IMAGE_NAME_LOWER=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') + echo "IMAGE_NAME_LOWER=${IMAGE_NAME_LOWER}" >> $GITHUB_ENV + + - name: πŸ—οΈ Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # ---------- GHCR ---------- + - name: πŸ”‘ Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GHCR_PAT }} + + - name: 🧱 Build and Push multi-arch image to GHCR + uses: docker/build-push-action@v6 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + tags: | + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:latest + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:${{ github.ref_name }} + labels: | + org.opencontainers.image.source=${{ github.repositoryUrl }} + org.opencontainers.image.description=RetroIPTVGuide Flask + SQLite Web App + org.opencontainers.image.licenses=CC-BY-NC-SA-4.0 + + - name: 🧹 Cleanup local images + run: docker image prune -af || true + + # ---------- Docker Hub ---------- + - name: 🐳 Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: 🧱 Build and Push single-arch image to Docker Hub + uses: docker/build-push-action@v6 + with: + context: . + push: true + platforms: linux/amd64 + provenance: false + tags: | + thehack904/retroiptvguide:latest + thehack904/retroiptvguide:${{ github.ref_name }} + labels: | + org.opencontainers.image.source=${{ github.repositoryUrl }} + org.opencontainers.image.description=RetroIPTVGuide Flask + SQLite Web App + org.opencontainers.image.licenses=CC-BY-NC-SA-4.0 + + # ---------- Summary ---------- + - name: 🧾 Post-build summary + run: | + echo "" + echo "βœ… GHCR and Docker Hub builds complete." + echo "🧩 Published image tags:" + echo " ghcr.io/thehack904/retroiptvguide:latest" + echo " ghcr.io/thehack904/retroiptvguide:${{ github.ref_name }}" + echo " thehack904/retroiptvguide:latest" + echo " thehack904/retroiptvguide:${{ github.ref_name }}" + echo "" + echo "πŸ”— Docker Hub: https://hub.docker.com/r/thehack904/retroiptvguide/tags" + echo "πŸ”— GHCR: https://github.com/thehack904?tab=packages&repo_name=RetroIPTVGuide" + echo "" + + # ---------- GHCR Cleanup ---------- + cleanup-ghcr: + name: 🧽 Cleanup old GHCR images + runs-on: ubuntu-latest + needs: build-and-push + permissions: + packages: write + steps: + - name: 🧹 Delete old GHCR package versions (keep 5) + uses: actions/delete-package-versions@v5 + with: + owner: thehack904 + package-name: retroiptvguide + package-type: container + min-versions-to-keep: 5 + token: ${{ secrets.GHCR_PAT }} + continue-on-error: true + + - name: 🧾 Summary + run: echo "βœ… GHCR cleanup complete β€” kept 5 latest versions." + + # ---------- Docker Hub Cleanup ---------- + cleanup-dockerhub: + name: 🧽 Cleanup old Docker Hub tags + runs-on: ubuntu-latest + needs: build-and-push + env: + USER: thehack904 + REPO: retroiptvguide + USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + steps: + - name: 🧹 Remove old Docker Hub tags (keep 5) + run: | + echo "πŸ”‘ Authenticating with Docker Hub API..." + AUTH_RESP=$(curl -s -X POST \ + -H "Content-Type: application/json" \ + -d "{\"username\": \"${USERNAME}\", \"password\": \"${TOKEN}\"}" \ + https://hub.docker.com/v2/users/login/) + JWT=$(echo $AUTH_RESP | jq -r .token) + + if [ -z "$JWT" ] || [ "$JWT" = "null" ]; then + echo "❌ Authentication failed β€” could not get JWT token." + exit 1 + fi + + echo "βœ… Authenticated successfully." + + TAGS=$(curl -s -H "Authorization: JWT ${JWT}" \ + "https://hub.docker.com/v2/repositories/${USER}/${REPO}/tags/?page_size=100" | + jq -r '.results[].name') + + if [ -z "$TAGS" ]; then + echo "⚠️ No tags found β€” skipping cleanup." + exit 0 + fi + + COUNT=0 + for TAG in $TAGS; do + COUNT=$((COUNT+1)) + if [ $COUNT -gt 5 ]; then + echo "🧹 Deleting $TAG ..." + curl -s -X DELETE -H "Authorization: JWT ${JWT}" \ + "https://hub.docker.com/v2/repositories/${USER}/${REPO}/tags/${TAG}/" >/dev/null + fi + done + + echo "βœ… Docker Hub cleanup complete β€” kept 5 newest tags." + diff --git a/CHANGELOG.md b/CHANGELOG.md index 80d56f4..30a0bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Δ‘ΕΊβ€œβ€˜ Changelog +## Changelog All notable changes to this project will be documented here. Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -14,6 +14,51 @@ This project follows [Semantic Versioning](https://semver.org/). --- +## [v3.2.0] - 2025-10-11 +### Added +- **Containerization & TrueNAS Deployment Support** + - Added official Dockerfile and `docker-compose.yml` for cross‑platform container deployments. + - Added **TrueNAS SCALE App chart** with persistent volume mapping (`/config`, `/logs`, `/data`). + - Added GitHub Actions workflow for automatic GHCR image builds. + - Docker image published at: + `ghcr.io/thehack904/retroiptvguide:latest` +- Integrated automatic build‑and‑push pipeline using GitHub Actions and GHCR_PAT authentication. +- Added healthcheck and restart policies in Docker configuration. + +### Changed +- Documentation updated for container installation (Docker/TrueNAS) as the new primary method. +- Legacy Python and system installers moved to β€œmanual install” section. + +### Fixed +- Corrected GHCR tag formatting for TrueNAS (eliminated `:latest:latest` errors). +- Fixed workflow permissions with explicit `packages: write` and PAT authentication. +--- + +## v3.1.0 - 2025-10-09 +### Added +- New **RetroIPTVGuide Raspberry Pi headless installer** (`retroiptv_rpi.sh`) + - Detects Raspberry Pi 3 / 4 / 5 models and auto-configures GPU memory + - Creates dedicated `iptv` user and installs to `/home/iptv/iptv-server` + - Logs all activity to `/var/log/retroiptvguide/install-YYYYMMDD-HHMMSS.log` + - Adds `--yes` and `--agree` flags for fully unattended installs + - Includes automatic environment checks for SD card size, RAM, and swap + +### Changed +- **Installer alignment:** + - Raspberry Pi installer now mirrors Debian / Windows structure + - Replaced all `apt` usage with `apt-get` for stable scripting + - Added verified, silenced `set_gpu_mem()` function that suppresses `rfkill` Wi-Fi warnings + - Enhanced post-install verification loop (up to 15 s) to confirm Flask web service readiness +- **bump_version.py:** now updates both `install.sh` and `retroiptv_rpi.sh` versions automatically +- Unified version tagging across all installers (`VERSION="x.y.z"` format) + +### Fixed +- Eliminated false-positive Wi-Fi β€œblocked by rfkill” messages during GPU configuration +- Corrected early-trigger HTTP service check timing on slower Pi 3/4 boards +- Ensured consistent permissions and ownership under `/home/iptv` + +--- + ## [v3.0.1] - 2025-10-07 ### Added - **EPG Fallback System** diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d91bdf4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,57 @@ +# ============================================ +# RetroIPTVGuide - Dockerfile +# ============================================ +FROM python:3.12-slim + +LABEL maintainer="thehack904" +LABEL description="RetroIPTVGuide Flask + SQLite Web App" +LABEL version="3.1.0" + +# -------------------------------------------- +# Environment setup +# -------------------------------------------- +ENV PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 \ + APP_HOME=/app + +WORKDIR $APP_HOME + +# -------------------------------------------- +# Install minimal system dependencies +# -------------------------------------------- +RUN apt-get update && apt-get install -y --no-install-recommends \ + tini \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# -------------------------------------------- +# Copy and install Python dependencies +# -------------------------------------------- +COPY requirements.txt ./ +RUN pip install --upgrade pip && pip install -r requirements.txt + +# -------------------------------------------- +# Copy application code +# -------------------------------------------- +COPY . . + +# -------------------------------------------- +# Create persistent directories for TrueNAS mounts +# -------------------------------------------- +RUN mkdir -p /app/config /app/logs /app/data + +# -------------------------------------------- +# Expose Flask port +# -------------------------------------------- +EXPOSE 5000 + +# -------------------------------------------- +# Use tini as init for graceful shutdown handling +# -------------------------------------------- +ENTRYPOINT ["/usr/bin/tini", "--"] + +# -------------------------------------------- +# Start the Flask app +# (Change app.py to wsgi.py if you ever switch to gunicorn) +# -------------------------------------------- +CMD ["python", "app.py"] diff --git a/INSTALL.md b/INSTALL.md index f044906..3246db8 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,10 +1,13 @@ # Installation Guide +**Version:** v3.2.0 +**Last Updated:** 2025-10-11 + ## Requirements - Python 3.10+ (Linux) / Python 3.12+ (Windows) -- **Linux (Debian/Ubuntu with systemd)** or **Windows 10/11** +- **Linux (Debian/Ubuntu with systemd)**, **Windows 10/11**, or **Raspberry Pi 3 / 4 / 5 (Headless OS) / Docker** - Administrative privileges: - - **Linux/WSL:** run install/uninstall with `sudo` + - **Linux/WSL/Raspberry Pi:** run install/uninstall with `sudo` - **Windows:** run from an Administrator **PowerShell** session --- @@ -15,34 +18,25 @@ Clone the repository and run the installer. Choose the command based on your OS. ### Linux / WSL -#### Option 1: One-liner (quick setup) +#### One-liner ```bash git clone https://github.com/thehack904/RetroIPTVGuide.git && cd RetroIPTVGuide && sudo chmod +x install.sh && sudo ./install.sh ``` -or - -#### Option 2: Multi-line (step-by-step) -```bash -git clone https://github.com/thehack904/RetroIPTVGuide.git -cd RetroIPTVGuide -sudo chmod +x install.sh -sudo ./install.sh -``` **What the installer does (Linux/WSL):** -- Detects Linux/WSL environment -- Ensures script is run with sudo -- Creates a system user `iptv` -- Installs into `/home/iptv/iptv-server` -- Ensures `python3-venv` is installed -- Creates Python virtual environment and installs dependencies -- Creates and enables the `iptv-server` systemd service -- Starts the service +- Detects Linux/WSL environment +- Ensures script is run with sudo +- Creates a system user `iptv` +- Installs into `/home/iptv/iptv-server` +- Ensures `python3-venv` is installed +- Creates Python virtual environment and installs dependencies +- Creates and enables the `iptv-server` systemd service +- Starts the service - Logs the install to `install_YYYY-MM-DD_HH-MM-SS.log` --- -### Windows 10/11 +### Windows 10 / 11 Run this one-liner from an **Administrator PowerShell** prompt: @@ -51,18 +45,75 @@ Invoke-WebRequest https://github.com/thehack904/RetroIPTVGuide/archive/refs/head ``` **What the installer does (Windows):** -- Bootstraps Chocolatey (if missing) -- Installs dependencies: `python`, `git`, `nssm` -- Registers Windows App Paths for `python` / `python3` -- Adds Python to Git Bash (`~/.bashrc`) -- Clones RetroIPTVGuide and runs `install.sh` under Git Bash to set up venv + requirements -- Creates an NSSM service to run `venv\Scripts\python.exe app.py` -- Opens Windows Firewall port 5000 -- Starts the RetroIPTVGuide service +- Bootstraps Chocolatey (if missing) +- Installs dependencies: `python`, `git`, `nssm` +- Registers Windows App Paths for `python` / `python3` +- Adds Python to Git Bash (`~/.bashrc`) +- Clones RetroIPTVGuide and runs `install.sh` under Git Bash to set up venv + requirements +- Creates an NSSM service to run `venv\Scripts\python.exe app.py` +- Opens Windows Firewall port 5000 +- Starts the RetroIPTVGuide service - Logs the install to `install_YYYY-MM-DD_HH-MM-SS.log` --- +### Raspberry Pi 3 / 4 / 5 (Headless Edition) + +#### Interactive install +```bash +curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/main/retroiptv_rpi.sh | sudo bash -s install +``` + +#### Unattended / non-interactive +```bash +curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/main/retroiptv_rpi.sh | sudo bash -s install --yes --agree +``` + +**What the installer does (Raspberry Pi):** +- Detects Pi model (3 / 4 / 5) +- Installs required packages (`python3-venv`, `ffmpeg`, `git`, etc.) using `apt-get` +- Creates user `iptv` and installs into `/home/iptv/iptv-server` +- Configures GPU memory automatically (128 MB on Pi 3 / 256 MB on Pi 4/5) +- Sets up Python virtual environment and dependencies +- Creates systemd service `retroiptvguide` +- Performs post-install HTTP check (localhost:5000) with up-to-15 s polling +- Logs all activity to `/var/log/retroiptvguide/install-TIMESTAMP.log` +- Optionally reboots to apply GPU memory changes + +**Requirements** +- Raspberry Pi OS (Bookworm or later) +- Minimum 8 GB SD card and 1 GB RAM (512 MB swap recommended) +- SSH or console access with sudo + +--- + +## πŸš€ Containerized Deployment + +RetroIPTVGuide v3.2.0 introduces **official Docker and TrueNAS SCALE App support**, allowing one‑click installation and persistent storage. + +### 🧱 Docker (Generic Linux / macOS / Windows) + +#### Using Docker Compose + +```bash +git clone https://github.com/thehack904/RetroIPTVGuide.git +cd RetroIPTVGuide/docker +cp .env.example .env +docker compose up -d +``` + + +## 🐳 Quick Docker Run + +The fastest way to launch **RetroIPTVGuide v3.2.0**: + +```bash +docker pull ghcr.io/thehack904/retroiptvguide:latest +docker run -d --name retroiptvguide -p 5000:5000 -e TZ=America/Chicago -e SECRET_KEY=$(openssl rand -hex 32) -v $(pwd)/config:/app/config -v $(pwd)/logs:/app/logs -v $(pwd)/data:/app/data ghcr.io/thehack904/retroiptvguide:latest +``` + +--- + ## Access Once installed, open your browser: @@ -72,69 +123,45 @@ http://:5000 ``` Default login: **admin / strongpassword123** +⚠️ This is a **BETA** build for internal network use only. --- ## πŸ”„ Updating ### Linux / WSL - -#### Quick update (one-liner) ```bash -sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && git fetch --all && git reset --hard origin/main" && sudo systemctl restart iptv-server.service +sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && git fetch --all && git reset --hard origin/main" && sudo systemctl daemon-reload && sudo systemctl restart iptv-server.service ``` -or -#### Step-by-step +### Raspberry Pi ```bash -sudo -u iptv bash -H -cd /home/iptv/iptv-server -git fetch --all -git reset --hard origin/main -exit -sudo systemctl restart iptv-server.service +sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && git fetch --all && git reset --hard origin/main" && sudo systemctl daemon-reload && sudo systemctl restart retroiptvguide.service ``` ---- - -### Windows 10/11 - -From an **Administrator PowerShell** prompt, go to your RetroIPTVGuide folder and run: - +### Windows 10 / 11 ```powershell git fetch --all ; git reset --hard origin/main ; Restart-Service RetroIPTVGuide ``` -or -#### Step-by-step -```powershell -git fetch --all -git reset --hard origin/main -Restart-Service RetroIPTVGuide +#### Docker +```bash +docker compose pull && docker compose up -d ``` -This will: -- Fetch the latest code from GitHub -- Reset your repo to the latest `windows` branch -- Restart the RetroIPTVGuide service (installed via NSSM) - --- ## Uninstallation ### Linux / WSL ```bash -sudo chmod +x uninstall.sh -sudo ./uninstall.sh +sudo -u iptv bash -H -c "cd /home/iptv/iptv-server" && sudo bash /home/iptv/iptv-server/uninstall.sh ``` -**What the uninstaller does (Linux/WSL):** -- Stops and disables the systemd service -- Removes the systemd unit file -- Deletes the `iptv` system user and related logs -- Removes the Python virtual environment - ---- +### Raspberry Pi +```bash +curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/main/retroiptv_rpi.sh | sudo bash -s uninstall --yes +``` ### Windows From an Administrator PowerShell prompt: @@ -142,22 +169,19 @@ From an Administrator PowerShell prompt: .\uninstall_windows.ps1 ``` -**What the uninstaller does (Windows):** -- Stops and removes the NSSM service -- Removes the Python virtual environment -- Deletes the Windows Firewall rule (port 5000) -- Lists remaining Chocolatey packages -- Prompts whether to uninstall **all Chocolatey packages (including Chocolatey itself)** +#### Docker +```bash +docker compose down -v +``` +**Each uninstaller stops its service, removes environment files, and cleans logs.** ⚠️ To completely remove the project, manually delete the project folder after uninstalling. - --- ## License -Licensed under CC BY-NC-SA 4.0. See LICENSE for details. +Licensed under CC BY-NC-SA 4.0. See `LICENSE` for details. --- ⚠️ **Initial BETA Notice** -This project is currently in **BETA**. -It should **not** be exposed directly to the Internet or used in production without additional hardening. +This project is currently in **BETA** and should **not** be exposed directly to the Internet or used in production without additional hardening. diff --git a/README.md b/README.md index 739ad57..383ba19 100644 --- a/README.md +++ b/README.md @@ -1,102 +1,218 @@ # RetroIPTVGuide -![Version](https://img.shields.io/badge/version-v3.0.1-blue) +

+ + Version + + + GHCR + + + Build Status + + + License + +

+ + +--- + +## πŸ“¦ Image Information + +| Registry | Image | Architectures | Updated | +|-----------|--------|----------------|----------| +| **GitHub Container Registry** | `ghcr.io/thehack904/retroiptvguide:latest` | amd64 / arm64 | Automatically via CI/CD | + +--- RetroIPTVGuide is an IPTV Web Interface inspired by 90s/2000s cable TV guides. -It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https://github.com/ErsatzTV/ErsatzTV/tree/main) but should support any `.m3u` and `.xml` IPTV source. +It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https://github.com/ErsatzTV/ErsatzTV/tree/main) but supports any `.m3u`, `.m3u8`, and `.xml` IPTV source. +Now includes **Docker and TrueNAS SCALE deployment support** for easy installation and persistence. -ΰΉ‚οΏ½οΏ½ΰΉΰΈ˜οΏ½ **Note:** This is still a BETA release. It is not recommended for direct Internet/public-facing deployments. +⚠️ **Note:** This is still a BETA release. It is not recommended for direct Internet/public-facing deployments. - [Installation / Uninstall Guide](INSTALL.md) - [Changelog](CHANGELOG.md) - [Roadmap](ROADMAP.md) - [License](LICENSE) -## ΰΉ‚οΏ½ΰΈˆ Features (v3.0.0) -- ΰΉοΏ½β€β€˜ **User Authentication** - - Login/logout system with hashed passwords. - - Admin and regular user accounts. - - Password change functionality. - - Admin-only user management (add/delete users). -- ΰΉοΏ½β€œΰΈ **Tuner Management** - - Multiple tuner support stored in `tuners.db`. - - Switch between active tuners via the web UI. - - Update `.m3u` and `.xml` tuner URLs (persisted in DB). -- ΰΉοΏ½β€œΰΈš **Guide & Playback** - - Program guide rendered from XMLTV with automatic fallback for missing data. - - Channels without guide entries display β€œNo Guide Data Available”. - - Video playback using HTML5 + HLS.js. - - Playback events logged with user + channel + timestamp. -- ΰΉοΏ½β€œβ€˜ **Logging** - - Activity log (`activity.log`) records authentication events, tuner changes, playback, and admin actions. - - Admin-only **Logs page** with real-time log viewing. - - Log file size display with color coding. - - Admin-only โ€�Clear Logsโ€� button to truncate logs. -- ๐��จ **UI Enhancements** - - Unified header across all pages (Guide, Logs, Add User, Delete User, Change Password, Change Tuner, Login). - - Active tuner display + live clock in header. - - **Themes submenu** with multiple options: - - Light - - Dark - - AOL/CompuServe - - TV Guide Magazine - - Theme persistence stored in browser localStorage, applied instantly across all pages. - - **About Page under Settings menu** โ€” shows version, Python, OS, uptime, paths. -- ΰΉ‚οΏ½οΏ½ΰΉΰΈ˜οΏ½ **System** - - Automatic initialization of `users.db` and `tuners.db` on first run. - - SQLite databases use WAL mode for better concurrency. - - Preloads tuner/channel/guide data from DB on startup. - - **Cross-platform installers (Linux/Windows) (v3.0.0)**. - - **Uninstaller scripts (Linux/Windows) (v3.0.0)**. - - **Automated version bump tool (`bump_version.py`) (v3.0.0)**. +--- +## πŸš€ Containerized Deployment (v3.2.0) + +### 🐳 Docker +```bash +docker pull ghcr.io/thehack904/retroiptvguide:latest +docker run -d -p 5000:5000 ghcr.io/thehack904/retroiptvguide:latest +``` +Access the web interface at: +`http://:5000` + +### 🧩 TrueNAS SCALE App +- Upload the provided `retroiptvguide-3.2.0.zip` chart. +- Repository: `ghcr.io/thehack904/retroiptvguide` +- Tag: `latest` +- Exposes port `5000`. + +--- + +## ✨ Features (v3.2.0) + +- Official **Docker / TrueNAS** support with persistent volumes. +- Automatic build/publish to **GHCR** via GitHub Actions. +- Same RetroIPTVGuide web interface and EPG features from v3.1.x. +- Backward compatible with Linux, Windows, and Raspberry Pi installs. + +--- + +### πŸ”‘ User Authentication +- Login/logout system with hashed passwords. +- Admin and regular user accounts. +- Password change functionality. +- Admin-only user management (add/delete users). + +### πŸ“‘ Tuner Management +- Multiple tuner support stored in `tuners.db`. +- Switch between active tuners via the web UI. +- Update `.m3u`, `.m3u8`, and `.xml` tuner URLs (persisted in DB). +- Active tuner refreshes instantly when changed β€” **no logout required**. +- Detection for invalid XML inputs (e.g., `.m3u` pasted into `.xml` field). + +### πŸ“Ί Guide & Playback +- Program guide rendered from XMLTV data. +- **Automatic fallback:** Channels missing XMLTV data display *β€œNo Guide Data Available”*. +- Channel list parsed from M3U playlist. +- Video playback using HTML5 + HLS.js. +- Playback events logged with user + channel + timestamp. +- Scalable time grid and responsive EPG layout. + +### πŸ“‘ Logging +- `activity.log` records authentication events, tuner changes, playback, and admin actions. +- Admin-only **Logs page** with real-time log viewing. +- Log file size display with color coding. +- Admin-only β€œClear Logs” button to truncate logs. + +### 🎨 UI Enhancements +- Unified header across all pages: Guide, Logs, Add User, Delete User, Change Password, Change Tuner, and Login. +- Active tuner display + live clock in header. +- β€œNo Guide Data Available” placeholders styled in gray/italic with dashed border. +- **Themes submenu** with multiple options: + - Light + - Dark + - AOL/CompuServe + - TV Guide Magazine +- Theme persistence stored in browser localStorage, applied instantly across all pages. +- **About Page under Settings** β€” shows version, Python, OS, uptime, and paths. +- **Login Page Redesign (v3.0.1)**: + - Floating centered login box with 3D shadow. + - RetroIPTVGuide logo positioned upper-right. + +### βš™οΈ System +- Automatic initialization of `users.db` and `tuners.db` on first run. +- SQLite databases use WAL mode for better concurrency. +- Preloads tuner/channel/guide data from DB on startup. +- **Cross-platform installers:** + - Linux / WSL (`install.sh`) + - Windows (`install_windows.ps1`) + - Raspberry Pi (`retroiptv_rpi.sh`) +- **Uninstaller scripts for all platforms** +- **Automated version bump tool (`bump_version.py`)** β€” now updates both `install.sh` and `retroiptv_rpi.sh`. + +--- + +## 🧩 Version History + +| Version | Date | Key Features | +|----------|------|---------------| +| **v3.2.0** | 2025-10-11 | Containerized Deployment / TrueNAS Scale App installer | +| **v3.1.0** | 2025-10-09 | Raspberry Pi installer, verified GPU setup, improved HTTP service check | +| **v3.0.1** | 2025-10-07 | EPG fallback system, tuner refresh fix, login redesign | +| **v3.0.0** | 2025-10-03 | Windows installer/uninstaller, cross-platform setup, unified UI | +| **v2.3.x** | 2025-09 | Unified theming, About page, installer logging, tuner rename/delete | +| **v2.0.0** | 2025-09 | Persistent tuners.db, user logs, unified headers | +| **v1.x.x** | 2025-08 | Initial IPTV Flask prototype | --- -## ๐��� Browser Compatibility -This project is designed to work with **all major browsers**. -It has been tested on: +## 🌐 Browser Compatibility +RetroIPTVGuide is compatible with all modern browsers: + - Firefox - Chrome - Safari - Edge -## ๐�’ป Tested Devices & OS -The web interface has been tested on: -- **Ubuntu (desktop/server)** +--- + +## πŸ’» Tested Devices & Operating Systems +- **Ubuntu 24.04 (desktop/server)** +- **TrueNAS SCALE (Docker)** +- **Windows 10 / 11** +- **Raspberry Pi 3B+ / 4 / 5 (Raspberry Pi OS Bookworm)** +- **macOS Monterey / Ventura** - **iOS (mobile/tablet)** -- **Android (Samsung Mobile Phone)** -- **macOS** -- **Windows 10/11** -- **MacOS** -- **Windows** +- **Android (Samsung / Pixel)** + +--- -## ๐���๏ธ� Installation Platform -- **Debian Based Linux (desktop/server)** -- **Windows 10/11** +## πŸ› οΈ Installation Platforms +- Debian-based Linux (Ubuntu, Pop!\_OS, Mint) +- Windows 10/11 (via PowerShell + NSSM) +- Raspberry Pi 3 / 4 / 5 (Headless OS) +- Docker (Generic Linux / macOS / Windows) -## ΰΉοΏ½β€œΰΈš Screenshots +--- + +## πŸ“Έ Screenshots -## ΰΉοΏ½β€œΰΈš Guide Page +### πŸ“Ί Guide Page ![Guide Screenshot](docs/screenshots/guide.png) -## ΰΉοΏ½β€œΰΈš Video Pop Out -![Video Pop Out](docs/screenshots/guide_with_video_breakout.png) +### πŸ“Ί Video Pop Out +![Guide Pop Out](docs/screenshots/guide_with_video_breakout.png) -## ΰΉοΏ½β€œΰΈš Video Pop Out on Desktop +### πŸ’» Desktop Pop Out ![Desktop Pop Out](docs/screenshots/video_breakout_desktop.png) -## ΰΉοΏ½β€œΰΈš TV Guide Magazine Theme +### πŸ“° TV Guide Magazine Theme ![TV Guide Theme](docs/screenshots/TV_Guide_Theme.png) -## ΰΉοΏ½β€œΰΈš AOL / CompuServe Theme -![AOL / CompuServe Theme](docs/screenshots/AOL_Compuserve_Theme.png) +### πŸ’Ύ AOL / CompuServe Theme +![AOL Theme](docs/screenshots/AOL_Compuserve_Theme.png) --- -## ๐�ค� Contributing -Contributions are welcome! Hereโ€�s how you can help: -1. **Report Issues**: Found a bug or want to suggest a feature? Open an [issue](../../issues). -2. **Submit Pull Requests**: Fork the repo, make changes, and submit a PR. Please ensure code is tested before submitting. -3. **Improve Documentation**: Help refine the installation guide, add screenshots, or improve explanations in the README. +## 🀝 Contributing + +Contributions are welcome! Here’s how you can help: + +1. **Report Issues** – Found a bug or want to suggest a feature? Open an [issue](../../issues). +2. **Submit Pull Requests** – Fork, modify, test, and submit PRs for new features or fixes. +3. **Improve Documentation** – Add screenshots, examples, or clearer explanations. + +All contributions will be reviewed before merging into the main branch. + +--- + +## 🧭 Roadmap (Next Planned Features) +- [ ] `.m3u8` single-channel tuner support +- [ ] Log filtering and pagination +- [ ] Guide search/filter +- [ ] Favorites and notifications +- [ ] Responsive mobile layout +- [ ] Auto-refresh EPG schedule + +See [ROADMAP.md](ROADMAP.md) for full details. + +--- + +## 🧰 Maintainer Notes +- **Repo:** [RetroIPTVGuide](https://github.com/thehack904/RetroIPTVGuide) +- **Maintainer:** J.H. +- **License:** [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) +- **Version:** v3.2.0 +- **Release Date:** 2025-10-11 + +--- -All contributions will be reviewed by the project maintainer before merging. +Β© 2025 RetroIPTVGuide Project β€” *Licensed under CC BY-NC-SA 4.0. Inspired by the golden era of cable TV.* diff --git a/ROADMAP.md b/ROADMAP.md index 7704779..30bdda8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -10,7 +10,7 @@ These are **not yet implemented**, but provide a development path for future rel ### 1. Tuner Management - [x] Add ability to **add/remove tuners** from the UI (v2.3.0). - [x] Add ability to rename tuners via the UI (v2.3.0). -- [ ] Support for **.m3u8 single-channel playlists** as tuner sources (planned v3.1.0). +- [ ] Support for **.m3u8 single-channel playlists** as tuner sources (planned v3.2.0). - Option A: Special-case `.m3u8` handling in parser. - Option B: Add explicit `hls` column to `tuners.db`. - [x] Validate tuner URLs (ping/check format before saving) (v2.0.0). @@ -22,6 +22,7 @@ These are **not yet implemented**, but provide a development path for future rel - [ ] Add system health checks (e.g., tuner reachability, XMLTV freshness) to logs. - [x] **Admin log management**: add button/route to clear logs (with confirmation) (v2.3.1). - [x] Display log file size on logs page (v2.3.1) +- [x] Post-install HTTP service verification added in Pi installer (v3.1.0) ### 3. Guide & Playback - [ ] Add **search/filter box** to guide for channels/programs. @@ -39,17 +40,22 @@ These are **not yet implemented**, but provide a development path for future rel - [ ] Unify CSS across all templates (minimize inline styles). - [ ] Make guide responsive (mobile/tablet view). - [ ] Add dark/light theme auto-detect from browser/system. -- [ ] Frozen header Timeline to prevent scrolling with channel listing +- [ ] Frozen header Timeline to prevent scrolling with channel listing - [x] About page under Settings menu (v2.3.1) ### 6. Cross-platform -- [ ] Create installable container. -- [ ] Create MacOS install/executable. -- [x] Create Microsoft Windows install/executable (full support via PowerShell + NSSM service) (v3.0.0) -- [x] Add uninstall_windows.ps1 and uninstall.bat (v3.0.0) -- [x] Windows installer now bootstraps Chocolatey, installs Python, Git, NSSM, and configures service (v3.0.0) +- [x] Create installable container. +- [ ] Create MacOS install/executable. +- [x] Create Microsoft Windows install/executable (full support via PowerShell + NSSM service) (v3.0.0) +- [x] Add uninstall_windows.ps1 and uninstall.bat (v3.0.0) +- [x] Windows installer bootstraps Chocolatey, installs Python, Git, NSSM, and configures service (v3.0.0) - [x] Windows uninstaller cleans service, firewall rule, and optionally removes Chocolatey (v3.0.0) - - [ ] Validate/test installer fully on Windows environments + - [ ] Validate/test installer fully on Windows environments +- [x] **Add Raspberry Pi headless installer (v3.1.0)** + - Detects Pi 3 / 4 / 5 models and sets GPU memory dynamically + - Installs under `/home/iptv/iptv-server` using user `iptv` + - Adds post-install HTTP verification and log summary + - Logs full install to `/var/log/retroiptvguide/install-TIMESTAMP.log` ### 7. New Features - [ ] Add the ability to have an auto play video stream upon login from a specific channel (Ersatz currently) to act similar to the 90/2000's tv guide that played "Commercials" until a channel was selected. @@ -59,44 +65,66 @@ These are **not yet implemented**, but provide a development path for future rel - [ ] Add **safety checks** in `add_tuner()`: - Prevent inserting duplicate tuner names. - Validate XML/M3U URLs are not empty before committing to DB. +- [x] Add **GPU verification** after `raspi-config` call (v3.1.0). +- [x] Suppress `rfkill` Wi-Fi message during GPU configuration (v3.1.0). +- [x] Post-install adaptive HTTP check loop (15s poll) (v3.1.0). --- ## βš™οΈ Technical Improvements -- [x] Add uninstall.sh (v2.3.0) - - [ ] Validate/test uninstall script fully on Windows environments -- [ ] Add https support +- [x] Add uninstall.sh (v2.3.0). + - [ ] Validate/test uninstall script fully on Windows environments. +- [ ] Add HTTPS support. - [ ] Refactor tuner handling to rely only on DB (remove in-memory fallback). - [ ] Add migrations for DB changes (via Alembic or custom script). - [ ] Containerize app (Dockerfile + Compose for deployment). - [ ] Add test suite for tuner parsing, authentication, and logging. -- [x] **Automated version bump tool** (`bump_version.py`) that updates `APP_VERSION` in `app.py` and creates a new section in `CHANGELOG.md` (v2.3.1). +- [x] **Automated version bump tool** (`bump_version.py`) now updates: + - `APP_VERSION` in `app.py` + - `install.sh` + - `retroiptv_rpi.sh` + - Adds new section in `CHANGELOG.md` (v3.1.0). --- ## πŸ“… Priority Suggestions -- Short term: (none β€” unified UI headers already completed in v2.0.0). -- Medium term: log filtering (still pending). -- Medium term: Test and harden installer/uninstaller on mixed Windows environments (v3.0.0 complete, further refinements planned). -- Long term: .m3u8 support, DB logs, recording functionality. +- Short term: finalize Docker image testing across TrueNAS and generic Linux. +- Medium term: implement `.m3u8` tuner and DB log storage (v3.3.x). +- Long term: HTTPS support and mobile UI redesign. --- -## βœ… Completed -- [x] Unified theming across all admin/user pages with Themes submenu and persistent setTheme logic (v2.3.2) -- [x] Tuner add/remove via UI (v2.3.0). -- [x] Tuner rename via UI (v2.3.0). -- [x] Tuner delete via UI (v2.3.0). -- [x] Tuner URL validation (v2.0.0). -- [x] Unified UI headers across templates (v2.0.0). -- [x] Installer logging (timestamped log files) (v2.3.0). -- [x] Environment detection in `install.sh` (Linux, WSL, Git Bash) (v2.3.0). -- [x] Unified cross-platform `install.sh` (v2.3.0). -- [x] Cross-platform `uninstall.sh` with sudo/admin checks and safe cleanup (v2.3.0). -- [x] Basic Windows installer support (Git Bash + PowerShell bootstrap) (v2.3.0). +## πŸ“ Installer Enhancement: Kiosk vs Headless Mode (Planned) +**Target Version:** v3.2.0 +**Status:** Planned +**Effort:** Medium +- Add an interactive mode selector to the Raspberry Pi installer. +- Headless mode β†’ install to `/home/iptv/iptv-server` with service user `iptv`. +- Kiosk mode β†’ install to `/opt/RetroIPTVGuide` and auto-launch Chromium in fullscreen displaying RetroIPTVGuide. +- Support command-line flags: `--mode kiosk` or `--mode headless` for non-interactive installs. +- Ensure logs and services are properly separated between modes. +--- +## βœ… Completed (v3.2.0) +- [x] **Containerization & TrueNAS Deployment Support** + - Dockerfile and docker‑compose finalized for GHCR. + - TrueNAS SCALE App chart added for persistent deployment. + - CI/CD publishing pipeline via GitHub Actions and GHCR_PAT. + - Updated documentation (INSTALL, README, CHANGELOG). + +## βœ… Completed (v3.1.0) +- [x] **Raspberry Pi headless installer completed** (`retroiptv_rpi.sh`). +- [x] Aligned Pi installer with Debian/Windows structure. +- [x] Added logging to `/var/log/retroiptvguide/`. +- [x] Added adaptive HTTP service verification. +- [x] Added GPU verification with silent `raspi-config` call. +- [x] Added system resource check (SD card size, RAM, swap). +- [x] Integrated `--yes` and `--agree` installer flags. +- [x] Verified functionality on Pi 3 and Pi 4. + +--- ## βœ… Completed (v3.0.0) -- [x] Full Windows installer/uninstaller support with NSSM service, firewall rule, and Chocolatey integration (v3.0.0). -- [x] Documentation updates (README.md, INSTALL.md) to reflect Windows support (v3.0.0). +- [x] Full Windows installer/uninstaller support with NSSM service, firewall rule, and Chocolatey integration. +- [x] Documentation updates (README.md, INSTALL.md) to reflect Windows support. diff --git a/app.py b/app.py index 47e405e..cac8920 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,5 @@ -APP_VERSION = "v3.0.1" -APP_RELEASE_DATE = "2025-09-26" +APP_VERSION = "v3.2.0" +APP_RELEASE_DATE = "2025-10-11" from flask import Flask, render_template, request, redirect, url_for, flash from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user @@ -133,6 +133,14 @@ def init_tuners_db(): "Tuner 2": { "m3u": "http://iptv2.lan:8500/iptv/channels.m3u", "xml": "http://iptv2.lan:8500/iptv/xmltv.xml" + }, + "Plex": { + "m3u": "https://raw.githubusercontent.com/iptv-org/iptv/refs/heads/master/streams/us_plex.m3u", + "xml": "https://raw.githubusercontent.com/iptv-org/iptv/refs/heads/master/streams/us_plex.m3u" + }, + "Tubi": { + "m3u": "https://raw.githubusercontent.com/iptv-org/iptv/refs/heads/master/streams/us_tubi.m3u", + "xml": "https://raw.githubusercontent.com/iptv-org/iptv/refs/heads/master/streams/us_tubi.m3u" } } for name, urls in defaults.items(): diff --git a/bump_version.py b/bump_version.py index d62f28b..83b3f40 100644 --- a/bump_version.py +++ b/bump_version.py @@ -13,12 +13,16 @@ import subprocess from pathlib import Path +# --- FILE TARGETS --- APP_FILE = Path("app.py") CHANGELOG_FILE = Path("CHANGELOG.md") INSTALL_WIN = Path("install_windows.ps1") UNINSTALL_WIN = Path("uninstall_windows.ps1") UNINSTALL_SH = Path("uninstall.sh") +INSTALL_SH = Path("install.sh") +RPI_INSTALL_SH = Path("retroiptv_rpi.sh") +# ------------------------------------------------------- def update_app_py(new_version: str): """Update APP_VERSION in app.py, add if missing""" content = APP_FILE.read_text().splitlines() @@ -80,7 +84,6 @@ def update_script_version(file: Path, new_version: str, is_bash: bool): updated = [] found = False - # Regex for version line if is_bash: pattern = re.compile(r'^\s*VERSION\s*=\s*".*"') replacement = f'VERSION="{new_version}"' @@ -96,7 +99,6 @@ def update_script_version(file: Path, new_version: str, is_bash: bool): updated.append(line) if not found: - # Insert at top updated.insert(0, replacement) print(f"ℹ️ VERSION not found in {file}, added at top") @@ -107,8 +109,14 @@ def git_commit(new_version: str): """Commit changes with git""" try: subprocess.run( - ["git", "add", str(APP_FILE), str(CHANGELOG_FILE), - str(INSTALL_WIN), str(UNINSTALL_WIN), str(UNINSTALL_SH)], + ["git", "add", + str(APP_FILE), + str(CHANGELOG_FILE), + str(INSTALL_WIN), + str(UNINSTALL_WIN), + str(UNINSTALL_SH), + str(INSTALL_SH), + str(RPI_INSTALL_SH)], check=True ) subprocess.run( @@ -130,14 +138,15 @@ def main(): update_app_py(new_version) update_changelog(new_version) - # Update other scripts + # Update all installers/uninstallers update_script_version(INSTALL_WIN, new_version, is_bash=False) update_script_version(UNINSTALL_WIN, new_version, is_bash=False) update_script_version(UNINSTALL_SH, new_version, is_bash=True) + update_script_version(INSTALL_SH, new_version, is_bash=True) + update_script_version(RPI_INSTALL_SH, new_version, is_bash=True) if do_commit: git_commit(new_version) if __name__ == "__main__": main() - diff --git a/docker/.env.example b/docker/.env.example new file mode 100644 index 0000000..6513382 --- /dev/null +++ b/docker/.env.example @@ -0,0 +1,18 @@ +# ============================================ +# RetroIPTVGuide Environment Configuration +# ============================================ + +# System Settings +TZ=America/Chicago +FLASK_ENV=production +PYTHONUNBUFFERED=1 + +# Security +SECRET_KEY=change_me_securely + +# Files / Logs +DATABASE_FILE=retroiptv.db +LOG_FILE=retroiptv.log + +# Internal Flask Port +FLASK_PORT=5000 diff --git a/docker/README_DOCKER.md b/docker/README_DOCKER.md new file mode 100644 index 0000000..37b7f6c --- /dev/null +++ b/docker/README_DOCKER.md @@ -0,0 +1,112 @@ +# 🐳 RetroIPTVGuide Docker Deployment + +This folder contains everything you need to deploy **RetroIPTVGuide** via Docker or Docker Compose. + +--- + +## πŸš€ Quick Start + +### 1️⃣ Clone the repository and navigate into the Docker directory +```bash +git clone https://github.com/thehack904/RetroIPTVGuide.git +cd RetroIPTVGuide/docker +``` + +### 2️⃣ Create a `.env` file from the example +```bash +cp .env.example .env +``` +Edit `.env` to set your timezone and secret key. + +### 3️⃣ Launch the container +```bash +docker compose up -d +``` + +### 4️⃣ Access the web interface +``` +http://:5000 +``` + +--- + +## πŸ”„ Updating +```bash +docker compose pull && docker compose up -d +``` + +--- + +## 🧹 Uninstalling +```bash +docker compose down -v +``` +This stops and removes the container, volumes, and network. + +--- + +## 🧱 Directory Layout +``` +docker/ +β”œβ”€β”€ docker-compose.yml +β”œβ”€β”€ .env.example +β”œβ”€β”€ config/ β†’ Persistent configuration files +β”œβ”€β”€ data/ β†’ SQLite database files +└── logs/ β†’ Application logs +``` +Docker automatically creates these directories on first run if they don’t exist. + +--- + +## 🧠 Notes +- The container image supports both **amd64** and **arm64** (e.g. Raspberry Pi). +- Default exposed port: **5000** +- Default image: `ghcr.io/thehack904/retroiptvguide:latest` +- Restart policy: `unless-stopped` +- Logs, configs, and data persist between updates. + +--- + +## 🧩 Example Commands + +View logs: +```bash +docker compose logs -f +``` + +Restart the container: +```bash +docker compose restart +``` + +Stop the container: +```bash +docker compose down +``` + +--- + +## 🧰 Customization + +You can override settings directly in the `.env` file: + +| Variable | Description | Example | +|-----------|--------------|----------| +| `TZ` | Timezone | `America/New_York` | +| `FLASK_ENV` | Flask environment | `production` | +| `SECRET_KEY` | Random secure key | `openssl rand -hex 32` | +| `DATABASE_FILE` | SQLite DB filename | `retroiptv.db` | +| `LOG_FILE` | Log file name | `retroiptv.log` | + +--- + +## 🧭 Compatibility + +βœ… Docker Desktop (Windows/macOS) +βœ… Linux (Ubuntu, Debian, Arch, etc.) +βœ… TrueNAS SCALE (Compose Stack or App) +βœ… Raspberry Pi (ARM builds supported) + +--- + +Β© 2025 RetroIPTVGuide β€” Licensed under CC BY-NC-SA 4.0 diff --git a/docker/config/.gitkeep b/docker/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker/data/.gitkeep b/docker/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..7c36f82 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.9" + +services: + retroiptvguide: + container_name: retroiptvguide + image: ghcr.io/thehack904/retroiptvguide:latest + restart: unless-stopped + ports: + - "5000:5000" + env_file: + - .env + volumes: + - ./config:/app/config + - ./logs:/app/logs + - ./data:/app/data + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:5000"] + interval: 30s + timeout: 5s + retries: 3 diff --git a/docker/logs/.gitkeep b/docker/logs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/install.sh b/install.sh index d17c79a..178ea1f 100644 --- a/install.sh +++ b/install.sh @@ -1,7 +1,9 @@ #!/bin/bash set -e -VERSION="3.0.1" +VERSION="3.2.0" # RetroIPTVGuide installer version +# RetroIPTVGuide Debian/Ubuntu Installer +# License: CC BY-NC-SA 4.0 TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") LOGFILE="install_${TIMESTAMP}.log" diff --git a/install_windows.ps1 b/install_windows.ps1 index 2bf2ccf..e1941b4 100644 --- a/install_windows.ps1 +++ b/install_windows.ps1 @@ -1,4 +1,4 @@ -$VERSION = "3.0.0" +$VERSION = "3.2.0" <# RetroIPTVGuide Windows Installer Clean version with only prerequisite checks and service setup diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh new file mode 100644 index 0000000..16c8150 --- /dev/null +++ b/retroiptv_rpi.sh @@ -0,0 +1,301 @@ +#!/bin/bash +VERSION="3.2.0" # RetroIPTVGuide Raspberry Pi installer version +# RetroIPTVGuide Raspberry Pi Installer (Headless, Pi3/4/5) +# Installs to /home/iptv/iptv-server for consistency with Debian/Windows +# Logs to /var/log/retroiptvguide/install-YYYYMMDD-HHMMSS.log +# License: CC BY-NC-SA 4.0 + + +# --- Banner --- +cat <<'EOF' +β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ +β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ +β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆβ–‘β–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ +β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ +β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ +β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆβ–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ +β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–ˆβ–ˆ β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ + +EOF +echo "===========================================================================" +echo " RetroIPTVGuide | Raspberry Pi Edition (Headless)" +echo "===========================================================================" +echo "" + +set -e + +# --- Logging --- +LOG_DIR="/var/log/retroiptvguide" +TIMESTAMP=$(date +"%Y%m%d-%H%M%S") +LOG_FILE="$LOG_DIR/install-$TIMESTAMP.log" +sudo mkdir -p "$LOG_DIR" +sudo chmod 755 "$LOG_DIR" +exec > >(tee -a "$LOG_FILE") 2>&1 +echo "Log file: $LOG_FILE" +echo "" + +# --- Vars --- +APP_USER="iptv" +APP_DIR="/home/$APP_USER/iptv-server" +SERVICE_FILE="/etc/systemd/system/retroiptvguide.service" +CONFIG_FILE="/boot/config.txt" + +ACTION="$1" +AUTO_YES=false +AUTO_AGREE=false +for arg in "$@"; do + case "$arg" in + --yes|-y) AUTO_YES=true ;; + --agree|-a) AUTO_AGREE=true ;; + esac +done + +# --- Helper functions --- +set_gpu_mem() { + local val="$1" + if command -v raspi-config >/dev/null 2>&1; then + # Quietly apply GPU memory change and suppress unrelated warnings + sudo raspi-config nonint set_config_var gpu_mem "$val" "$CONFIG_FILE" 2>/dev/null || true + + # Verify it was written correctly + local current_val + current_val=$(grep -E "^gpu_mem=" "$CONFIG_FILE" 2>/dev/null | tail -n1 | cut -d'=' -f2) + if [ "$current_val" = "$val" ]; then + echo "βœ… Verified: GPU memory successfully set to ${val}MB" | tee -a "$LOG_FILE" + else + echo "⚠️ Warning: Could not confirm gpu_mem=$val in $CONFIG_FILE" | tee -a "$LOG_FILE" + fi + else + # Manual fallback if raspi-config missing + sudo sed -i -E 's/^\s*gpu_mem\s*=.*/gpu_mem='"$val"'/g' "$CONFIG_FILE" 2>/dev/null || true + if ! grep -qE '^\s*gpu_mem\s*=' "$CONFIG_FILE" 2>/dev/null; then + echo "gpu_mem=$val" | sudo tee -a "$CONFIG_FILE" >/dev/null + fi + echo "βœ… Fallback: gpu_mem set manually to ${val}MB" | tee -a "$LOG_FILE" + fi +} +ensure_owned_by_iptv() { sudo chown -R "$APP_USER:$APP_USER" "$APP_DIR"; } +pip_install_as_iptv() { sudo -u "$APP_USER" bash -lc "$1"; } + +#====================== INSTALL ======================# +install_app() { + echo "" + echo "============================================================" + echo " RetroIPTVGuide Raspberry Pi Headless Installer " + echo "============================================================" + echo "" + echo "This installer will perform the following actions:" + echo " - Detect Raspberry Pi model (3, 4, or newer)" + echo " - Check storage, RAM, and swap configuration" + echo " - Install dependencies (Python3, ffmpeg, etc.)" + echo " - Create system user 'iptv' (if not present)" + echo " - Clone RetroIPTVGuide into /home/iptv/iptv-server" + echo " - Configure Python virtual environment and systemd service" + echo " - Auto-configure GPU memory for headless operation" + echo " - Enable the retroiptvguide service on boot" + echo " - Optionally reboot when done" + echo "" + echo "By continuing, you agree that:" + echo " - This software should only be run on internal networks." + echo " - It must not be exposed to the public Internet." + echo " - You accept all risks; no warranty is provided." + echo "" + + if [ "$AUTO_AGREE" = true ]; then + echo "[Auto-agree] Terms accepted via --agree flag." + else + read -p "Do you agree to these terms? (yes/no): " agreement + [[ "$agreement" != "yes" ]] && echo "Installation aborted." && exit 1 + echo "Agreement accepted. Continuing..." + fi + echo "" + + # Detect Pi model + PI_MODEL=$(tr -d '\0' < /proc/device-tree/model 2>/dev/null || echo "Unknown Model") + case "$PI_MODEL" in + *"Raspberry Pi 5"*) PI_TYPE="pi5" ;; + *"Raspberry Pi 4"*) PI_TYPE="pi4" ;; + *"Raspberry Pi 3"*) PI_TYPE="pi3" ;; + *) PI_TYPE="unknown" ;; + esac + echo "Detected board: $PI_MODEL ($PI_TYPE)" + echo "" + + # Check SD card and swap + echo "Checking storage and memory..." + ROOT_DEV=$(df / | tail -1 | awk '{print $1}') + SD_SIZE=$(df -h / | awk 'NR==2 {print $2}') + MEM_TOTAL=$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo) + SWAP_TOTAL=$(awk '/SwapTotal/ {print int($2/1024)}' /proc/meminfo) + echo "Root device: $ROOT_DEV" + echo "Storage size: $SD_SIZE" + echo "RAM: ${MEM_TOTAL}MB | Swap: ${SWAP_TOTAL}MB" + if [ "$MEM_TOTAL" -lt 1000 ] && [ "$SWAP_TOTAL" -lt 400 ]; then + echo "⚠️ Warning: <1GB RAM and <400MB swap β€” increase swap to 1GB for stability:" + echo " sudo dphys-swapfile swapoff && sudo sed -i 's/^CONF_SWAPSIZE=.*/CONF_SWAPSIZE=1024/' /etc/dphys-swapfile && sudo dphys-swapfile setup && sudo dphys-swapfile swapon" + fi + if df -BG / | awk 'NR==2 {exit ($2<8)}'; then + echo "⚠️ Warning: Root filesystem smaller than 8GB β€” limited space for logs/updates." + fi + echo "" + + # Create user if needed + if ! id "$APP_USER" &>/dev/null; then + echo "Creating user '$APP_USER'..." + sudo useradd -m -r -s /usr/sbin/nologin "$APP_USER" + fi + sudo mkdir -p "$APP_DIR" + ensure_owned_by_iptv + + # Update & deps + echo "Installing dependencies..." + sudo apt-get update -y + sudo apt-get dist-upgrade -y + sudo apt-get install -y git python3 python3-venv python3-pip ffmpeg mesa-utils v4l-utils raspi-config || true + + # Clone or update repo + if [ ! -d "$APP_DIR/.git" ]; then + sudo -u "$APP_USER" git clone https://github.com/thehack904/RetroIPTVGuide.git "$APP_DIR" + else + ( cd "$APP_DIR" && sudo -u "$APP_USER" git pull ) + fi + + # Python venv setup + if [ ! -d "$APP_DIR/venv" ]; then + sudo -u "$APP_USER" python3 -m venv "$APP_DIR/venv" + fi + pip_install_as_iptv "source '$APP_DIR/venv/bin/activate' && pip install --upgrade pip" + if [ -f "$APP_DIR/requirements.txt" ]; then + pip_install_as_iptv "source '$APP_DIR/venv/bin/activate' && pip install -r '$APP_DIR/requirements.txt'" + else + pip_install_as_iptv "source '$APP_DIR/venv/bin/activate' && pip install Flask" + fi + sudo -u "$APP_USER" mkdir -p "$APP_DIR/data" || true + + # GPU memory by model + echo "Configuring GPU memory..." + case "$PI_TYPE" in + pi4|pi5) set_gpu_mem 256 ;; + pi3|*) set_gpu_mem 128 ;; + esac + + # systemd service + echo "Creating systemd service..." + sudo tee "$SERVICE_FILE" >/dev/null </dev/null 2>&1; then + echo "βœ… Web interface responding on port 5000 (after ${wait_time}s)." + echo "βœ… Verified: HTTP response received." | tee -a "$LOG_FILE" + break + fi + sleep 2 + wait_time=$((wait_time+2)) + done + if [ $wait_time -ge $max_wait ]; then + echo "⚠️ Service active, but no HTTP response after ${max_wait}s. Check logs in $LOG_FILE." + echo "⚠️ Possible slow startup on first run (SQLite or dependencies still initializing)." | tee -a "$LOG_FILE" + fi + else + echo "❌ Service not active. Run: sudo systemctl status retroiptvguide" + fi + echo "" + + + # Optional reboot + if [ "$AUTO_YES" = false ]; then + read -t 10 -p "Reboot now to apply GPU memory? (Y/n, default Y in 10s): " R || R="Y" + R=${R:-Y} + if [[ "$R" =~ ^[Yy]$ ]]; then + echo "Rebooting..." + sleep 2 + sudo reboot + else + echo "Reboot skipped. Run 'sudo reboot' later if GPU memory changed." + fi + fi +} + +#====================== UNINSTALL ======================# +uninstall_app() { + echo "" + echo "============================================================" + echo " RetroIPTVGuide Uninstaller (Headless) " + echo "============================================================" + + if [ "$AUTO_YES" = false ]; then + read -p "Proceed with uninstallation? (yes/no): " c + [[ "$c" != "yes" ]] && echo "Aborted." && exit 1 + fi + + systemctl stop retroiptvguide 2>/dev/null || true + systemctl disable retroiptvguide 2>/dev/null || true + [ -f "$SERVICE_FILE" ] && sudo rm -f "$SERVICE_FILE" && sudo systemctl daemon-reload + + if [ -d "$APP_DIR" ]; then + if [ "$AUTO_YES" = true ]; then + sudo rm -rf "$APP_DIR" + echo "Removed $APP_DIR" + else + read -p "Delete $APP_DIR? (yes/no): " d + [[ "$d" == "yes" ]] && sudo rm -rf "$APP_DIR" && echo "Removed $APP_DIR" + fi + fi + + echo "" + echo "Uninstallation complete. End time: $(date)" + echo "Log file: $LOG_FILE" + echo "" +} + +#====================== MAIN ======================# +case "$ACTION" in + install) install_app ;; + uninstall) uninstall_app ;; + *) + echo "Usage: sudo $0 install|uninstall [--yes|-y] [--agree|-a]" + exit 1 + ;; +esac diff --git a/uninstall.sh b/uninstall.sh index dfd6b21..c89c69e 100644 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,4 +1,4 @@ -VERSION="3.0.0" +VERSION="3.2.0" #!/usr/bin/env bash # RetroIPTVGuide uninstall script # Run with sudo on Linux; run from Administrator shell on Windows @@ -33,7 +33,7 @@ if [[ "$ENVIRONMENT" == "LINUX" || "$ENVIRONMENT" == "WSL" ]]; then exit 1 fi elif [[ "$ENVIRONMENT" == "GITBASH" ]]; then - # Git Bash doesn’t expose EUID reliably, just warn the user + # Git Bash doesnÒ€ℒt expose EUID reliably, just warn the user echo "NOTE: On Windows, ensure Git Bash is running with Administrator privileges." fi diff --git a/uninstall_windows.ps1 b/uninstall_windows.ps1 index ff49b83..8971eb7 100644 --- a/uninstall_windows.ps1 +++ b/uninstall_windows.ps1 @@ -1,4 +1,4 @@ -$VERSION = "3.0.0" +$VERSION = "3.2.0" # RetroIPTVGuide Windows Uninstaller # ==================================