From 1d4f3f3d458a17d8171d2648b605b6e0c7669566 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 5 Feb 2026 23:17:44 -0600 Subject: [PATCH] Update 4.4.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Added - (Windows Powershell Install Script) Better validation checks in Windows Powershell install script. Added Ensure-AppFiles Function (NEW) - Added *BETA* Unraid .xml for testing ### Changed - (Windows Powershell Install Script) Enhanced Upgrade-PipAndInstallReqs Function, Ensure-Service Function, Do-Install Function ### Fixed - (Windows Powershell Install Script) Fixed update code bug from v.4.3.0, Fixed Syntax Errors, Update-RetroIPTVGuide Function, Ensure-Choco Function - Broken Chocolatey Detection - Docker - Add persistant directories for: /app/users.db → symlink to /app/config/users.db /app/tuners.db → symlink to /app/config/tuners.db --- CHANGELOG.md | 17 ++ INSTALL.md | 4 +- README.md | 11 +- ROADMAP.md | 7 +- app.py | 4 +- docker/docker-compose.yml | 5 +- docker/entrypoint_fixdb.sh | 23 +++ docker/unraid/README-unraid.md | 44 +++++ docker/unraid/RetroIPTVGuide.xml | 34 ++++ retroiptv_linux.sh | 2 +- retroiptv_rpi.sh | 2 +- retroiptv_windows.bat | 4 +- retroiptv_windows.ps1 | 299 +++++++++++++++++++++++++++---- 13 files changed, 408 insertions(+), 48 deletions(-) create mode 100755 docker/entrypoint_fixdb.sh create mode 100644 docker/unraid/README-unraid.md create mode 100644 docker/unraid/RetroIPTVGuide.xml mode change 100644 => 100755 retroiptv_windows.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 039f910..656c7b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,23 @@ This project follows [Semantic Versioning](https://semver.org/). --- +## v4.4.0 - 2026-02-05 + +### Added +- (Windows Powershell Install Script) Better validation checks in Windows Powershell install script. Added Ensure-AppFiles Function (NEW) +- Added *BETA* Unraid .xml for testing + +### Changed +- (Windows Powershell Install Script) Enhanced Upgrade-PipAndInstallReqs Function, Ensure-Service Function, Do-Install Function + +### Fixed +- (Windows Powershell Install Script) Fixed update code bug from v.4.3.0, Fixed Syntax Errors, Update-RetroIPTVGuide Function, Ensure-Choco Function - Broken Chocolatey Detection +- Docker - Add persistant directories for: +/app/users.db → symlink to /app/config/users.db +/app/tuners.db → symlink to /app/config/tuners.db + +--- + ## v4.3.0 - 2025-11-14 ### Added diff --git a/INSTALL.md b/INSTALL.md index e3ded14..b8eed00 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,7 +1,7 @@ # Installation Guide -**Version:** v4.3.0 -**Last Updated:** 2025-11-14 +**Version:** v4.4.0 +**Last Updated:** 2026-02-05 --- diff --git a/README.md b/README.md index a558a77..a0e2702 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# 📺 RetroIPTVGuide v4.3.0 +# 📺 RetroIPTVGuide v4.4.0

- Version + Version GHCR @@ -62,6 +62,9 @@ docker run -d -p 5000:5000 ghcr.io/thehack904/retroiptvguide:latest - Tag: `latest` - Exposes port `5000`. +### 🧩 Unraid (Docker) — **BETA / Manual Install Only** +See docker/unraid/ for RetroIPTVGuide.xml / README-unraid.md for installation instructions + ### 🐧 Linux ```bash curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/main/retroiptv_linux.sh | sudo bash -s install --agree --yes @@ -75,8 +78,8 @@ curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/main/retro ### 🪟 Windows (PowerShell) ```powershell Set-ExecutionPolicy Bypass -Scope Process -Force -Invoke-WebRequest https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/main/retroiptv_windows.ps1 -OutFile retroiptv_windows.ps1 -.\retroiptv_windows.ps1 install +Invoke-WebRequest https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/main/retroiptv_windows.bat -OutFile retroiptv_windows.bat +.\retroiptv_windows.bat install ``` ## 🌐 Access diff --git a/ROADMAP.md b/ROADMAP.md index 7c92c9a..215d980 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -4,7 +4,7 @@ This document tracks **planned upgrades** and ideas for improving the IPTV Flask These are **not yet implemented**, partially implemented, or completed in previous releases. --- -# Current Version: **v4.3.0 (2025-11-14)** +# Current Version: **v4.4.0 (2026-02-05)** ## 🔮 Feature Upgrades @@ -117,4 +117,7 @@ These are **not yet implemented**, partially implemented, or completed in previo - [ ] Casting Support (Chromecast) - [ ] Resize Pop Out Video - [ ] Resize video on page -- [ ] Auto load Channel from Guide / Hidden Channel / Sizzle Reels +- [ ] Auto load Channel from Guide / Hidden Channel / Sizzle Reels +- [ ] Adjustable scrolling speed of the Guide +- [ ] Output IPTV stream from built guide for re-broadcast as a channel +- [x] Unraid Template - in *BETA* diff --git a/app.py b/app.py index 1123e9e..969e2c4 100644 --- a/app.py +++ b/app.py @@ -1,6 +1,6 @@ # app.py — merged version (features from both sources) -APP_VERSION = "v4.3.0" -APP_RELEASE_DATE = "2025-11-14" +APP_VERSION = "v4.4.0" +APP_RELEASE_DATE = "2026-02-05" from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify, abort from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 7c36f82..14c0dc9 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.9" - services: retroiptvguide: container_name: retroiptvguide @@ -13,6 +11,9 @@ services: - ./config:/app/config - ./logs:/app/logs - ./data:/app/data + - ./entrypoint_fixdb.sh:/entrypoint_fixdb.sh:ro + entrypoint: ["sh", "/entrypoint_fixdb.sh"] + command: ["python", "app.py"] healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5000"] interval: 30s diff --git a/docker/entrypoint_fixdb.sh b/docker/entrypoint_fixdb.sh new file mode 100755 index 0000000..d81af22 --- /dev/null +++ b/docker/entrypoint_fixdb.sh @@ -0,0 +1,23 @@ +#!/bin/sh +set -eu + +mkdir -p /app/config /app/logs /app/data + +# One-time migration: if legacy DBs exist in /app, move into persisted config dir +for f in users.db tuners.db; do + if [ -f "/app/$f" ] && [ ! -f "/app/config/$f" ]; then + mv "/app/$f" "/app/config/$f" + fi +done + +# Force the app's relative DB paths to resolve into /app/config +for f in users.db tuners.db; do + # If a real file already exists and isn't a symlink, leave it (migration above should prevent this) + if [ -e "/app/$f" ] && [ ! -L "/app/$f" ]; then + continue + fi + ln -sf "/app/config/$f" "/app/$f" +done + +exec "$@" + diff --git a/docker/unraid/README-unraid.md b/docker/unraid/README-unraid.md new file mode 100644 index 0000000..ffedc0b --- /dev/null +++ b/docker/unraid/README-unraid.md @@ -0,0 +1,44 @@ +# RetroIPTVGuide – Unraid Template *BETA* + +This repository contains the Unraid Docker template for **RetroIPTVGuide**. + +## What this is +An Unraid-compatible XML template that pre-populates: +- Docker image (`ghcr.io/thehack904/retroiptvguide:latest`) +- WebUI port mapping +- Persistent volume mappings (`/app/config`, `/app/logs`, `/app/data`) +- Common environment variables (TZ, etc.) + +#### BETA Limitations +- Not indexed by **Community Applications** +- Template fields and defaults may change +- Limited Unraid-specific testing to date +- No migration guarantees between template revisions during beta + +## Install methods + +### Method 1: Manual install (works immediately) +Use this method if you do **not** use Community Applications, or you want to test quickly. + +1. In Unraid, go to **Docker** → **Add Container** +2. Click **Template** (or **Add Container** UI option) and locate the **Template URL** field +3. Paste the raw XML URL for this template: + + `https://raw.githubusercontent.com/thehack904/retroiptvguide-unraid/main/templates/RetroIPTVGuide.xml` + +4. Apply / install +5. Review port mappings and storage paths. +6. **IMPORTANT:** Set a secure value for `SECRET_KEY` before starting the container. +7. Start the container. + + +Notes: +- Feedback from Unraid users is welcome and will help promote this install method out of BETA. +- Updates to the XML are not automatically “pushed” into existing installs; users typically re-apply changes manually. + +### Method 2: Community Applications - Currently under development + +## Support +- Project: https://github.com/thehack904/retroiptvguide +- Issues: https://github.com/thehack904/retroiptvguide/issues + diff --git a/docker/unraid/RetroIPTVGuide.xml b/docker/unraid/RetroIPTVGuide.xml new file mode 100644 index 0000000..b31450f --- /dev/null +++ b/docker/unraid/RetroIPTVGuide.xml @@ -0,0 +1,34 @@ + + + RetroIPTVGuide + ghcr.io/thehack904/retroiptvguide:latest + https://ghcr.io + bridge + + bash + false + https://github.com/thehack904/retroiptvguide + https://github.com/thehack904/retroiptvguide + RetroIPTVGuide is an IPTV guide management system that provides a web interface for managing and viewing TV guides. + MediaApp:Video MediaServer:Video + http://[IP]:[PORT:5000]/ + + https://raw.githubusercontent.com/Squidly271/community.applications/master/source/community.applications/usr/local/emhttp/plugins/community.applications/images/question.png + + + + + + + 5000 + /mnt/user/appdata/retroiptvguide/config + /mnt/user/appdata/retroiptvguide/logs + /mnt/user/appdata/retroiptvguide/data + America/Chicago + production + 1 + change_me_securely + retroiptv.db + retroiptv.log + 5000 + diff --git a/retroiptv_linux.sh b/retroiptv_linux.sh index a1720aa..15c0897 100644 --- a/retroiptv_linux.sh +++ b/retroiptv_linux.sh @@ -3,7 +3,7 @@ # License: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) set -euo pipefail -VERSION="4.3.0" +VERSION="4.4.0" TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") LOGFILE="retroiptv_${TIMESTAMP}.log" exec > >(tee -a "$LOGFILE") 2>&1 diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh index c04bb10..da8e2ac 100644 --- a/retroiptv_rpi.sh +++ b/retroiptv_rpi.sh @@ -1,5 +1,5 @@ #!/bin/bash -VERSION="4.3.0" +VERSION="4.4.0" # 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 diff --git a/retroiptv_windows.bat b/retroiptv_windows.bat index edf890b..eb2ab0a 100644 --- a/retroiptv_windows.bat +++ b/retroiptv_windows.bat @@ -3,7 +3,7 @@ mode con: cols=160 lines=50 REM ============================================================ REM RetroIPTVGuide Windows Unified Installer / Uninstaller -REM Version: v4.3.0 +REM Version: v4.4.0 REM License: Creative Commons BY-NC-SA 4.0 REM ============================================================ @@ -31,7 +31,7 @@ if /i "%choice%"=="Y" ( :continue setlocal -set "VERSION=4.3.0" +set "VERSION=4.4.0" set "REPO_URL=https://github.com/thehack904/RetroIPTVGuide.git" set "ZIP_URL=https://github.com/thehack904/RetroIPTVGuide/archive/refs/heads/main.zip" set "INSTALL_DIR=%~dp0RetroIPTVGuide" diff --git a/retroiptv_windows.ps1 b/retroiptv_windows.ps1 old mode 100644 new mode 100755 index 7ae1eb2..a306f31 --- a/retroiptv_windows.ps1 +++ b/retroiptv_windows.ps1 @@ -1,7 +1,7 @@ <# RetroIPTVGuide Windows Installer/Uninstaller Filename: retroiptv_windows.ps1 -Version: 4.3.0 +Version: 4.4.0 License: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International https://creativecommons.org/licenses/by-nc-sa/4.0/ @@ -55,7 +55,7 @@ if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdent $ErrorActionPreference = 'Stop' $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8' -$VERSION = "4.3.0" +$VERSION = "4.4.0" $ScriptDir = Split-Path -Parent -Path $MyInvocation.MyCommand.Path Set-Location $ScriptDir @@ -104,13 +104,13 @@ try { Start-Transcript -Path $logFile -Append | Out-Null } catch {} "" $banner = @" -¦¦¦¦¦¦¦¦¦¦ ¦¦¦ ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ¦¦¦ ¦¦¦¦¦¦¦ ¦¦¦ ¦¦¦ -¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ -¦¦¦ ¦¦¦ ¦¦¦¦¦¦¦¦ ¦¦¦¦¦¦¦¦¦ ¦¦¦¦¦¦¦¦ ¦¦¦¦¦¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦¦¦¦¦¦¦ ¦¦¦¦¦¦¦¦ -¦¦¦¦¦¦¦¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦¦¦¦¦¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ -¦¦¦ ¦¦¦ ¦¦¦¦¦¦¦¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦ ¦¦¦ ¦¦¦ ¦¦¦¦¦¦ ¦¦¦ ¦¦¦¦¦¦¦¦¦¦ -¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦ ¦¦¦¦¦¦ ¦¦¦ ¦¦¦¦ ¦¦¦ ¦¦¦¦ ¦¦¦¦¦¦ ¦¦¦¦ ¦¦¦ -¦¦¦ ¦¦¦ ¦¦¦¦¦¦¦¦ ¦¦¦¦¦ ¦¦¦ ¦¦¦¦¦¦¦¦ ¦¦¦¦¦¦¦¦¦¦ ¦¦¦ ¦¦¦¦ ¦¦¦¦¦¦¦¦ ¦¦¦¦¦¦¦¦¦ ¦¦¦ ¦¦¦¦¦¦¦¦¦ ¦¦¦¦¦¦¦¦ + + + + + + + "@ try { @@ -177,6 +177,25 @@ By continuing, you acknowledge and agree that: # ------------------------------- function Ensure-Choco { Write-Info "Checking for Chocolatey..." + + $chocoPath = "C:\ProgramData\chocolatey" + $chocoBin = "$chocoPath\bin\choco.exe" + + # Check if Chocolatey directory exists but choco.exe is missing (broken install) + if ((Test-Path $chocoPath) -and -not (Test-Path $chocoBin)) { + Write-Warn "Broken Chocolatey installation detected. Removing..." + try { + Remove-Item -Path $chocoPath -Recurse -Force -ErrorAction Stop + Write-Ok "Broken installation removed." + Start-Sleep -Seconds 1 + } catch { + Write-ErrorMsg "Failed to remove broken Chocolatey installation at $chocoPath" + Write-ErrorMsg "Please manually delete this folder and run the script again." + throw + } + } + + # Check if choco is accessible if (-not (Get-Command choco.exe -ErrorAction SilentlyContinue)) { Write-Warn "Chocolatey not found. Installing..." # Allow TLS 1.2 @@ -184,7 +203,38 @@ function Ensure-Choco { Set-ExecutionPolicy Bypass -Scope Process -Force try { Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) - Write-Ok "Chocolatey installed." + + Write-Info "Refreshing environment variables..." + # Refresh PATH multiple ways to ensure it works + $env:ChocolateyInstall = "C:\ProgramData\chocolatey" + $machinePath = [System.Environment]::GetEnvironmentVariable("Path","Machine") + $userPath = [System.Environment]::GetEnvironmentVariable("Path","User") + $env:Path = "$machinePath;$userPath" + + # Give it a moment to settle + Start-Sleep -Seconds 2 + + # Verify choco is now available + if (-not (Get-Command choco.exe -ErrorAction SilentlyContinue)) { + # One more attempt - directly check if the file exists + if (Test-Path "$chocoPath\bin\choco.exe") { + Write-Warn "Chocolatey installed but not yet in PATH for this session." + Write-Warn "Manually adding to PATH..." + $env:Path = "$chocoPath\bin;$env:Path" + + # Final check + if (-not (Get-Command choco.exe -ErrorAction SilentlyContinue)) { + Write-ErrorMsg "Chocolatey installation completed but 'choco' command is still not available." + Write-ErrorMsg "Please close this window and run the script again." + throw "ChocoNotInPath" + } + } else { + Write-ErrorMsg "Chocolatey installation may have failed - choco.exe not found." + throw "ChocoInstallFailed" + } + } + + Write-Ok "Chocolatey installed successfully." } catch { Write-ErrorMsg "Failed to install Chocolatey. $_" throw @@ -196,7 +246,7 @@ function Ensure-Choco { function Ensure-ChocoPkg($pkgName) { if (-not (choco list --local-only | Select-String -Quiet ("^{0} " -f [regex]::Escape($pkgName)))) { - Write-Info "Installing $pkgName via Chocolatey..." + Write-Info "Installing $pkgName via Chocolatey...(This may take several minutes, please be patient)" choco install $pkgName -y | Out-Null Write-Ok "$pkgName installed." } else { @@ -247,17 +297,97 @@ function Upgrade-PipAndInstallReqs { & $VenvPy -m pip install --upgrade pip Write-Info "Installing requirements..." $req = Join-Path $ScriptDir "requirements.txt" + if (-not (Test-Path $req)) { - Write-Warn "requirements.txt not found in $ScriptDir; skipping package install." - } else { + Write-Warn "requirements.txt not found in $ScriptDir" + Write-Info "Downloading requirements.txt from GitHub..." + + $reqUrl = "https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/main/requirements.txt" + try { + # Download requirements.txt + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + $webClient = New-Object System.Net.WebClient + $webClient.DownloadFile($reqUrl, $req) + Write-Ok "requirements.txt downloaded successfully." + } catch { + Write-ErrorMsg "Failed to download requirements.txt from GitHub: $_" + Write-Warn "Skipping package installation." + return + } + } + + if (Test-Path $req) { + Write-Info "Installing Python packages from requirements.txt..." & $VenvPy -m pip install -r $req + Write-Ok "Python dependencies installed." + } else { + Write-Warn "requirements.txt still not found; skipping package install." } - Write-Ok "Python dependencies installed." } # ------------------------------- # NSSM service helpers # ------------------------------- +function Ensure-AppFiles { + Write-Info "Checking for required application files..." + + $appPy = Join-Path $ScriptDir "app.py" + + # Check if we're in a git repository + if (Test-Path (Join-Path $ScriptDir ".git")) { + Write-Ok "Running from git repository." + if (-not (Test-Path $appPy)) { + Write-ErrorMsg "app.py not found in repository. Repository may be corrupted." + throw "AppPyNotFound" + } + return + } + + # Not in a git repo - need to clone it + Write-Warn "This installer is not running from a git repository." + Write-Info "The RetroIPTVGuide repository will be cloned to continue installation." + + $installPath = "C:\RetroIPTVGuide" + $repoUrl = "https://github.com/thehack904/RetroIPTVGuide.git" + + if (Test-Path $installPath) { + Write-Warn "Directory $installPath already exists." + if (-not (Confirm-YesNo "Remove existing directory and clone fresh?")) { + Write-Warn "Installation aborted by user." + exit 1 + } + try { + Remove-Item -Path $installPath -Recurse -Force + Write-Ok "Existing directory removed." + } catch { + Write-ErrorMsg "Failed to remove existing directory: $_" + throw + } + } + + Write-Info "Cloning repository to $installPath..." + try { + git clone $repoUrl $installPath + if (-not $?) { + throw "Git clone failed" + } + Write-Ok "Repository cloned successfully." + } catch { + Write-ErrorMsg "Failed to clone repository: $_" + throw + } + + # Update script directory to the cloned repo + Write-Info "Switching to repository directory..." + Set-Location $installPath + $script:ScriptDir = $installPath + $script:VenvDir = Join-Path $ScriptDir "venv" + $script:VenvPy = Join-Path $VenvDir "Scripts\python.exe" + + Write-Ok "Now working from $installPath" +} + + function Ensure-Service { param([string] $Name) @@ -266,15 +396,25 @@ function Ensure-Service { $svc = Get-Service -Name $Name -ErrorAction SilentlyContinue if ($svc) { - Write-Warn "Service '$Name' already exists. It will be updated to use the current directory." - # stop first - try { Stop-Service -Name $Name -Force -ErrorAction SilentlyContinue } catch {} - # reconfigure below - } else { - Write-Info "Creating Windows service '$Name' (NSSM)..." - & $NssmExe install $Name $VenvPy "app.py" + Write-Warn "Service '$Name' already exists. Stopping and reconfiguring..." + # Stop the service completely + try { + & $NssmExe stop $Name | Out-Null + Start-Sleep -Seconds 2 + } catch {} + + # Remove the old service + try { + & $NssmExe remove $Name confirm | Out-Null + Start-Sleep -Seconds 1 + Write-Ok "Old service removed." + } catch {} } + # Create new service + Write-Info "Creating Windows service '$Name' (NSSM)..." + & $NssmExe install $Name $VenvPy "app.py" + # Configure AppDirectory / stdout / stderr / start type & $NssmExe set $Name AppDirectory $ScriptDir | Out-Null & $NssmExe set $Name Start SERVICE_AUTO_START | Out-Null @@ -288,9 +428,104 @@ function Ensure-Service { Write-Ok "Service '$Name' configured." Write-Info "Starting service..." + + # Start the service & $NssmExe start $Name | Out-Null - Start-Sleep -Seconds 1 - Write-Ok "Service start issued." + Start-Sleep -Seconds 3 + + # Check if it actually started + $svc = Get-Service -Name $Name -ErrorAction SilentlyContinue + if ($svc) { + if ($svc.Status -eq 'Running') { + Write-Ok "Service started successfully." + } elseif ($svc.Status -eq 'Paused') { + Write-Warn "Service is paused. Attempting to resume..." + try { + Resume-Service -Name $Name -ErrorAction Stop + Start-Sleep -Seconds 2 + $svc = Get-Service -Name $Name + if ($svc.Status -eq 'Running') { + Write-Ok "Service resumed successfully." + } else { + Write-Warn "Service status: $($svc.Status)" + } + } catch { + Write-Warn "Failed to resume service: $_" + } + } else { + Write-Warn "Service status: $($svc.Status)" + } + } +} + +function Ensure-Service { + param([string] $Name) + + # Install NSSM if missing + Ensure-ChocoPkg "nssm" + + $svc = Get-Service -Name $Name -ErrorAction SilentlyContinue + if ($svc) { + Write-Warn "Service '$Name' already exists. Stopping and reconfiguring..." + # Stop the service completely + try { + & $NssmExe stop $Name | Out-Null + Start-Sleep -Seconds 2 + } catch {} + + # Remove the old service + try { + & $NssmExe remove $Name confirm | Out-Null + Start-Sleep -Seconds 1 + Write-Ok "Old service removed." + } catch {} + } + + # Create new service + Write-Info "Creating Windows service '$Name' (NSSM)..." + & $NssmExe install $Name $VenvPy "app.py" + + # Configure AppDirectory / stdout / stderr / start type + & $NssmExe set $Name AppDirectory $ScriptDir | Out-Null + & $NssmExe set $Name Start SERVICE_AUTO_START | Out-Null + + $logDir = Join-Path $ScriptDir "logs" + if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } + & $NssmExe set $Name AppStdout (Join-Path $logDir "service_stdout.log") | Out-Null + & $NssmExe set $Name AppStderr (Join-Path $logDir "service_stderr.log") | Out-Null + & $NssmExe set $Name AppStopMethodConsole 1500 | Out-Null + & $NssmExe set $Name AppKillProcessTree 1 | Out-Null + + Write-Ok "Service '$Name' configured." + Write-Info "Starting service..." + + # Start the service + & $NssmExe start $Name | Out-Null + Start-Sleep -Seconds 3 + + # Check if it actually started + $svc = Get-Service -Name $Name -ErrorAction SilentlyContinue + if ($svc) { + if ($svc.Status -eq 'Running') { + Write-Ok "Service started successfully." + } elseif ($svc.Status -eq 'Paused') { + Write-Warn "Service is paused. Attempting to resume..." + try { + Resume-Service -Name $Name -ErrorAction Stop + Start-Sleep -Seconds 2 + $svc = Get-Service -Name $Name + if ($svc.Status -eq 'Running') { + Write-Ok "Service resumed successfully." + } else { + Write-Warn "Service status: $($svc.Status)" + } + } catch { + Write-Warn "Failed to resume service: $_" + } + } else { + Write-Warn "Service status: $($svc.Status)" + } + } } function Remove-ServiceSafe { @@ -390,6 +625,9 @@ function Do-Install { Ensure-ChocoPkg "python" Ensure-ChocoPkg "git" Ensure-ChocoPkg "nssm" + + # Make sure we have the application files + Ensure-AppFiles # Python & venv New-Venv -VenvPath $VenvDir @@ -411,7 +649,6 @@ function Do-Install { Write-Info ("Log file: {0}" -f $logFile) Write-Title "============================================================" } - # ------------------------------- # UNINSTALL # ------------------------------- @@ -473,7 +710,7 @@ function Do-Uninstall { Read-Host } -function Update-RetroIPTVGuide { +function Do-Update { Write-Host "" Write-Host "============================================================" Write-Host " RetroIPTVGuide Updater (Windows)" @@ -482,7 +719,7 @@ function Update-RetroIPTVGuide { $InstallPath = "C:\RetroIPTVGuide\iptv-server" if (-Not (Test-Path "$InstallPath\.git")) { - Write-Host "❌ Cannot update — this is not a git repository: $InstallPath" + Write-Host "Cannot update - this is not a git repository: $InstallPath" -ForegroundColor Red return } @@ -493,7 +730,7 @@ function Update-RetroIPTVGuide { git reset --hard origin/main } catch { - Write-Host "❌ Git update failed: $($_.Exception.Message)" + Write-Host "Git update failed: $($_.Exception.Message)" -ForegroundColor Red return } @@ -506,7 +743,7 @@ function Update-RetroIPTVGuide { & "$VenvPath\Scripts\pip.exe" install -r "$InstallPath\requirements.txt" } else { - Write-Host "⚠️ No virtual environment found. Recreating..." + Write-Host "No virtual environment found. Recreating..." -ForegroundColor Yellow python -m venv "$VenvPath" & "$VenvPath\Scripts\python.exe" -m pip install --upgrade pip & "$VenvPath\Scripts\pip.exe" install -r "$InstallPath\requirements.txt" @@ -520,7 +757,7 @@ function Update-RetroIPTVGuide { Start-Service RetroIPTVGuide } else { - Write-Host "⚠️ Service not installed. The app will run only manually." + Write-Host "Service not installed. The app will run only manually." -ForegroundColor Yellow } Write-Host "" @@ -530,7 +767,6 @@ function Update-RetroIPTVGuide { Write-Host "" } - if (-not $Action) { Write-Host "" Write-Host "RetroIPTVGuide Windows Installer Menu" -ForegroundColor Cyan @@ -566,7 +802,6 @@ try { Stop-Transcript | Out-Null Start-Sleep -Milliseconds 200 } catch {} -} Write-Host "" Write-Host "============================================================" -ForegroundColor Cyan @@ -574,4 +809,4 @@ try { Write-Host "You may review the log above or press ENTER to close this window." -ForegroundColor Yellow Write-Host "============================================================" Read-Host -} +} \ No newline at end of file