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
-
+
@@ -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