From a5f803069ec4ae5ba2bc9cf2a025584b5ed0c51b Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sun, 28 Sep 2025 16:54:20 -0500 Subject: [PATCH 1/5] Update install.sh --- install.sh | 158 +++++++++++++++-------------------------------------- 1 file changed, 43 insertions(+), 115 deletions(-) diff --git a/install.sh b/install.sh index 127da24..248d244 100644 --- a/install.sh +++ b/install.sh @@ -1,133 +1,61 @@ -#!/bin/bash -set -e - -VERSION="2.1.0" -TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") -LOGFILE="install_${TIMESTAMP}.log" +#!/usr/bin/env bash +# install.sh - Installer for RetroIPTVGuide +# Detects environment, creates venv, ensures pip is up-to-date only if needed. -# Log everything to file + console -exec > >(tee -a "$LOGFILE") 2>&1 +set -e -echo "=== RetroIPTVGuide Installer (v$VERSION) ===" -echo "Start time: $(date)" -echo "Log file: $LOGFILE" +echo "=== RetroIPTVGuide Installer ===" -# --- Detect Environment --- -if grep -qi microsoft /proc/version 2>/dev/null; then +# Detect environment +if grep -qi "microsoft" /proc/version 2>/dev/null; then ENVIRONMENT="WSL" -elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]]; then +elif [ -n "$WINDIR" ] && [ -x "/bin/bash" ] && uname -s | grep -qi "mingw"; then ENVIRONMENT="GITBASH" -elif [[ "$OSTYPE" == "linux-gnu"* ]]; then - ENVIRONMENT="LINUX" else - ENVIRONMENT="UNKNOWN" + ENVIRONMENT="LINUX" fi -echo "Detected environment: $ENVIRONMENT" +echo "Environment detected: $ENVIRONMENT" -# Ensure script is run with sudo on Linux/WSL -if [[ "$ENVIRONMENT" == "LINUX" || "$ENVIRONMENT" == "WSL" ]]; then - if [[ $EUID -ne 0 ]]; then - echo "This script must be run with sudo." - exit 1 - fi +# Ensure Python is available +if ! command -v python3 >/dev/null 2>&1 && ! command -v python >/dev/null 2>&1; then + echo "Python is not installed. Please install Python 3 and rerun." + exit 1 fi -# Variables -APP_USER="iptv" -APP_HOME="/home/$APP_USER" -APP_DIR="$APP_HOME/iptv-server" -SERVICE_FILE="/etc/systemd/system/iptv-server.service" - -# --- Linux/WSL Install Path --- -if [[ "$ENVIRONMENT" == "LINUX" || "$ENVIRONMENT" == "WSL" ]]; then - # Create system user if not exists - if id "$APP_USER" &>/dev/null; then - echo "User $APP_USER already exists." - else - echo "Creating iptv system user..." - adduser --system --home "$APP_HOME" --group "$APP_USER" - fi - - # Ensure python3-venv is installed - echo "Checking for python3-venv..." - if ! dpkg -s python3-venv >/dev/null 2>&1; then - echo "python3-venv not found. Installing..." - apt-get update - apt-get install -y python3-venv - else - echo "python3-venv is already installed." - fi - - # Create app directory - mkdir -p "$APP_DIR" - chown -R $APP_USER:$APP_USER "$APP_HOME" - - # Copy project files - echo "Copying project files..." - rsync -a --exclude 'venv' ./ "$APP_DIR/" - chown -R $APP_USER:$APP_USER "$APP_DIR" - - # Setup virtual environment - cd "$APP_DIR" - echo "Setting up Python virtual environment..." - sudo -u $APP_USER python3 -m venv venv - - echo "Upgrading pip..." - sudo -u $APP_USER $APP_DIR/venv/bin/pip install --upgrade pip - - echo "Installing requirements..." - sudo -u $APP_USER $APP_DIR/venv/bin/pip install -r "$APP_DIR/requirements.txt" +# Pick python executable +if command -v python3 >/dev/null 2>&1; then + PY=python3 +else + PY=python +fi - # Create systemd service - echo "Creating systemd service..." - cat > "$SERVICE_FILE" </dev/null 2>&1; then - echo "Error: Python not found in PATH. Please install Python 3 manually." - exit 1 - fi - echo "Setting up Python virtual environment..." - python -m venv venv - source venv/Scripts/activate - echo "Upgrading pip..." - pip install --upgrade pip - echo "Installing requirements..." - pip install -r requirements.txt - echo "Starting RetroIPTVGuide in development mode..." - python app.py & +echo "=== Installation complete. Activate venv with ===" +if [ "$ENVIRONMENT" = "GITBASH" ]; then + echo "source venv/Scripts/activate" else - echo "Unsupported environment: $OSTYPE" - exit 1 + echo "source venv/bin/activate" fi - -echo "" -echo "=== Installation complete! ===" -echo "End time: $(date)" -echo "Access the server in your browser at: http://:5000" -echo "Default login: admin / strongpassword123" -echo "NOTE: This is a **BETA build**. Do not expose it directly to the public internet." From 0639a4322b3ec55d4b9f8b165ca240684d3137b2 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sun, 28 Sep 2025 19:28:32 -0700 Subject: [PATCH 2/5] Windows Installer Testing --- install.bat | 2 + install_windows.ps1 | 558 ++++++++++++++++++++++++++++++++++++++++++ uninstall.bat | 2 + uninstall_windows.ps1 | 322 ++++++++++++++++++++++++ 4 files changed, 884 insertions(+) create mode 100644 install.bat create mode 100644 install_windows.ps1 create mode 100644 uninstall.bat create mode 100644 uninstall_windows.ps1 diff --git a/install.bat b/install.bat new file mode 100644 index 0000000..938f524 --- /dev/null +++ b/install.bat @@ -0,0 +1,2 @@ +@echo off +powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0install_windows.ps1" diff --git a/install_windows.ps1 b/install_windows.ps1 new file mode 100644 index 0000000..4447c95 --- /dev/null +++ b/install_windows.ps1 @@ -0,0 +1,558 @@ +<# install_windows.ps1 + Windows bootstrap for RetroIPTVGuide + - Prefer WSL if installed + - Else fallback to Git Bash + - Check/install Git + Python if missing + - Force Git Bash to cd into script root before cloning + - All output logged to file +#> + +$LogDir = Join-Path $PSScriptRoot "logs" +if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Force -Path $LogDir | Out-Null } +$TimeStamp = Get-Date -Format "yyyyMMdd_HHmmss" +$LogFile = Join-Path $LogDir "install_$TimeStamp.log" + +Start-Transcript -Path $LogFile -Force + +# Elevation check +$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) +if (-not $IsAdmin) { + Write-Host "Re-launching with Administrator privileges..." -ForegroundColor Yellow + Stop-Transcript + Start-Process -FilePath "powershell.exe" -Verb RunAs -ArgumentList "-ExecutionPolicy Bypass -File `"$PSCommandPath`"" + exit +} + +Write-Host "=== RetroIPTVGuide Windows Installer Bootstrap ===" -ForegroundColor Cyan +Write-Host "Timestamp: $(Get-Date)" +Write-Host "Log file: $LogFile" +Write-Host "OS: $([System.Environment]::OSVersion.VersionString)" + +# Elevation check +$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") +if (-not $IsAdmin) { + Write-Host "Re-launching with Administrator privileges..." -ForegroundColor Yellow +# --- PATCH BLOCK 1: Activation instructions --- +if ($env:ComSpec -like "*cmd.exe") { + $activation = ".\venv\Scripts\activate.bat" +} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { + $activation = ".\venv\Scripts\Activate.ps1" +} else { + $activation = "source venv/Scripts/activate" +} +Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green +Write-Host $activation -ForegroundColor Cyan + +# --- PATCH BLOCK 2: NSSM service setup --- +$nssmPath = "C:\nssm\nssm.exe" +if (-not (Test-Path $nssmPath)) { + try { + Write-Host "Downloading nssm..." -ForegroundColor Yellow + $nssmZip = Join-Path $env:TEMP "nssm.zip" + Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip + Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force + $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" + } catch { + Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." + $nssmPath = $null + } +} + +if ($nssmPath -and (Test-Path $nssmPath)) { + $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" + $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" + $appPath = Join-Path $TargetDir "app.py" + + Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow + & $nssmPath install RetroIPTVGuide $pythonExe $appPath + & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START + & $nssmPath start RetroIPTVGuide + Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green +} else { + Write-Warning "NSSM not available. Skipping service setup." +} +# --- END PATCH --- +# --- PATCH: Record Python version and path --- +$pythonExe = (Get-Command python.exe).Source +$pythonDir = Split-Path $pythonExe -Parent # <-- this gives Scripts +$pythonRoot = Split-Path $pythonDir -Parent # <-- this gives Python312 folder +$pythonVer = (& $pythonExe --version).Split()[1] + +$logDir = Join-Path $PSScriptRoot "logs" +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } +$verFile = Join-Path $logDir "python_version.txt" + +"Version=$pythonVer" | Out-File $verFile -Encoding ascii +"Path=$pythonRoot" | Out-File $verFile -Encoding ascii -Append +# --- END PATCH --- + Stop-Transcript + Start-Process -FilePath "powershell.exe" -Verb RunAs -ArgumentList "-NoProfile","-ExecutionPolicy","Bypass","-File","`"$PSCommandPath`"" + exit +} + +function CmdExists($name) { Get-Command $name -ErrorAction SilentlyContinue | Out-Null } + +# Step 1: Prefer WSL +$HasWslExe = CmdExists "wsl.exe" +if ($HasWslExe) { + $distros = & wsl.exe -l -q 2>$null + if ($LASTEXITCODE -eq 0 -and $distros -and $distros.Trim().Length -gt 0) { + Write-Host "WSL distribution detected. Installing inside WSL..." -ForegroundColor Cyan + wsl.exe -- bash -lc "git clone -b windows https://github.com/thehack904/RetroIPTVGuide.git && cd RetroIPTVGuide && chmod +x install.sh && ./install.sh" +# --- PATCH BLOCK 1: Activation instructions --- +if ($env:ComSpec -like "*cmd.exe") { + $activation = ".\venv\Scripts\activate.bat" +} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { + $activation = ".\venv\Scripts\Activate.ps1" +} else { + $activation = "source venv/Scripts/activate" +} +Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green +Write-Host $activation -ForegroundColor Cyan + +# --- PATCH BLOCK 2: NSSM service setup --- +$nssmPath = "C:\nssm\nssm.exe" +if (-not (Test-Path $nssmPath)) { + try { + Write-Host "Downloading nssm..." -ForegroundColor Yellow + $nssmZip = Join-Path $env:TEMP "nssm.zip" + Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip + Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force + $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" + } catch { + Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." + $nssmPath = $null + } +} + +if ($nssmPath -and (Test-Path $nssmPath)) { + $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" + $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" + $appPath = Join-Path $TargetDir "app.py" + + Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow + & $nssmPath install RetroIPTVGuide $pythonExe $appPath + & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START + & $nssmPath start RetroIPTVGuide + Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green +} else { + Write-Warning "NSSM not available. Skipping service setup." +} +# --- END PATCH --- +# --- PATCH: Record Python version and path --- +$pythonExe = (Get-Command python.exe).Source +$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts +$pythonVer = (& $pythonExe --version).Split()[1] + +$logDir = Join-Path $PSScriptRoot "logs" +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } +$verFile = Join-Path $logDir "python_version.txt" + +"Version=$pythonVer" | Out-File $verFile -Encoding ascii +"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append +# --- END PATCH --- + Stop-Transcript + exit $LASTEXITCODE + } else { + Write-Host "WSL present but no Linux distro installed." -ForegroundColor Yellow + try { + wsl.exe --install -d Ubuntu + Write-Host "Ubuntu installation initiated. Please reboot when prompted, then re-run this script." -ForegroundColor Green +# --- PATCH BLOCK 1: Activation instructions --- +if ($env:ComSpec -like "*cmd.exe") { + $activation = ".\venv\Scripts\activate.bat" +} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { + $activation = ".\venv\Scripts\Activate.ps1" +} else { + $activation = "source venv/Scripts/activate" +} +Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green +Write-Host $activation -ForegroundColor Cyan + +# --- PATCH BLOCK 2: NSSM service setup --- +$nssmPath = "C:\nssm\nssm.exe" +if (-not (Test-Path $nssmPath)) { + try { + Write-Host "Downloading nssm..." -ForegroundColor Yellow + $nssmZip = Join-Path $env:TEMP "nssm.zip" + Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip + Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force + $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" + } catch { + Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." + $nssmPath = $null + } +} + +if ($nssmPath -and (Test-Path $nssmPath)) { + $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" + $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" + $appPath = Join-Path $TargetDir "app.py" + + Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow + & $nssmPath install RetroIPTVGuide $pythonExe $appPath + & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START + & $nssmPath start RetroIPTVGuide + Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green +} else { + Write-Warning "NSSM not available. Skipping service setup." +} +# --- END PATCH --- +# --- PATCH: Record Python version and path --- +$pythonExe = (Get-Command python.exe).Source +$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts +$pythonVer = (& $pythonExe --version).Split()[1] + +$logDir = Join-Path $PSScriptRoot "logs" +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } +$verFile = Join-Path $logDir "python_version.txt" + +"Version=$pythonVer" | Out-File $verFile -Encoding ascii +"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append +# --- END PATCH --- + Stop-Transcript + exit 0 + } catch { + Write-Warning "Automatic WSL install failed. Install WSL manually, then rerun." +# --- PATCH BLOCK 1: Activation instructions --- +if ($env:ComSpec -like "*cmd.exe") { + $activation = ".\venv\Scripts\activate.bat" +} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { + $activation = ".\venv\Scripts\Activate.ps1" +} else { + $activation = "source venv/Scripts/activate" +} +Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green +Write-Host $activation -ForegroundColor Cyan + +# --- PATCH BLOCK 2: NSSM service setup --- +$nssmPath = "C:\nssm\nssm.exe" +if (-not (Test-Path $nssmPath)) { + try { + Write-Host "Downloading nssm..." -ForegroundColor Yellow + $nssmZip = Join-Path $env:TEMP "nssm.zip" + Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip + Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force + $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" + } catch { + Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." + $nssmPath = $null + } +} + +if ($nssmPath -and (Test-Path $nssmPath)) { + $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" + $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" + $appPath = Join-Path $TargetDir "app.py" + + Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow + & $nssmPath install RetroIPTVGuide $pythonExe $appPath + & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START + & $nssmPath start RetroIPTVGuide + Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green +} else { + Write-Warning "NSSM not available. Skipping service setup." +} +# --- END PATCH --- +# --- PATCH: Record Python version and path --- +$pythonExe = (Get-Command python.exe).Source +$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts +$pythonVer = (& $pythonExe --version).Split()[1] + +$logDir = Join-Path $PSScriptRoot "logs" +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } +$verFile = Join-Path $logDir "python_version.txt" + +"Version=$pythonVer" | Out-File $verFile -Encoding ascii +"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append +# --- END PATCH --- + Stop-Transcript + exit 1 + } + } +} + +# Step 2: Fallback to Git Bash +Write-Host "WSL not available. Falling back to Git Bash..." -ForegroundColor Yellow +$GitBashPath = "$Env:ProgramFiles\Git\bin\bash.exe" +if (-not (Test-Path $GitBashPath)) { $GitBashPath = "$Env:ProgramFiles(x86)\Git\bin\bash.exe" } + +if (-not (Test-Path $GitBashPath)) { + Write-Host "Git for Windows not found. Attempting to install..." -ForegroundColor Yellow + + if (CmdExists "winget") { + winget install -e --id Git.Git --silent + } elseif (CmdExists "choco") { + choco install git -y + } else { + # Fallback: direct download + silent install + try { + $Installer = "$env:TEMP\GitInstaller.exe" + Write-Host "Downloading Git for Windows installer..." -ForegroundColor Cyan + Invoke-WebRequest -Uri "https://github.com/git-for-windows/git/releases/download/v2.47.0.windows.1/Git-2.47.0-64-bit.exe" -OutFile $Installer + Write-Host "Running Git installer silently..." -ForegroundColor Cyan + Start-Process -FilePath $Installer -ArgumentList "/VERYSILENT","/NORESTART" -Wait + } catch { + Write-Error "Automatic Git install failed. Please install Git manually: https://git-scm.com/download/win" +# --- PATCH BLOCK 1: Activation instructions --- +if ($env:ComSpec -like "*cmd.exe") { + $activation = ".\venv\Scripts\activate.bat" +} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { + $activation = ".\venv\Scripts\Activate.ps1" +} else { + $activation = "source venv/Scripts/activate" +} +Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green +Write-Host $activation -ForegroundColor Cyan + +# --- PATCH BLOCK 2: NSSM service setup --- +$nssmPath = "C:\nssm\nssm.exe" +if (-not (Test-Path $nssmPath)) { + try { + Write-Host "Downloading nssm..." -ForegroundColor Yellow + $nssmZip = Join-Path $env:TEMP "nssm.zip" + Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip + Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force + $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" + } catch { + Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." + $nssmPath = $null + } +} + +if ($nssmPath -and (Test-Path $nssmPath)) { + $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" + $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" + $appPath = Join-Path $TargetDir "app.py" + + Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow + & $nssmPath install RetroIPTVGuide $pythonExe $appPath + & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START + & $nssmPath start RetroIPTVGuide + Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green +} else { + Write-Warning "NSSM not available. Skipping service setup." +} +# --- END PATCH --- +# --- PATCH: Record Python version and path --- +$pythonExe = (Get-Command python.exe).Source +$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts +$pythonVer = (& $pythonExe --version).Split()[1] + +$logDir = Join-Path $PSScriptRoot "logs" +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } +$verFile = Join-Path $logDir "python_version.txt" + +"Version=$pythonVer" | Out-File $verFile -Encoding ascii +"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append +# --- END PATCH --- + Stop-Transcript + exit 1 + } + } + + # Re-check after install + $GitBashPath = "$Env:ProgramFiles\Git\bin\bash.exe" + if (-not (Test-Path $GitBashPath)) { $GitBashPath = "$Env:ProgramFiles(x86)\Git\bin\bash.exe" } + if (-not (Test-Path $GitBashPath)) { + Write-Error "Git Bash still not found after install attempt." +# --- PATCH BLOCK 1: Activation instructions --- +if ($env:ComSpec -like "*cmd.exe") { + $activation = ".\venv\Scripts\activate.bat" +} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { + $activation = ".\venv\Scripts\Activate.ps1" +} else { + $activation = "source venv/Scripts/activate" +} +Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green +Write-Host $activation -ForegroundColor Cyan + +# --- PATCH BLOCK 2: NSSM service setup --- +$nssmPath = "C:\nssm\nssm.exe" +if (-not (Test-Path $nssmPath)) { + try { + Write-Host "Downloading nssm..." -ForegroundColor Yellow + $nssmZip = Join-Path $env:TEMP "nssm.zip" + Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip + Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force + $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" + } catch { + Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." + $nssmPath = $null + } +} + +if ($nssmPath -and (Test-Path $nssmPath)) { + $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" + $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" + $appPath = Join-Path $TargetDir "app.py" + + Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow + & $nssmPath install RetroIPTVGuide $pythonExe $appPath + & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START + & $nssmPath start RetroIPTVGuide + Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green +} else { + Write-Warning "NSSM not available. Skipping service setup." +} +# --- END PATCH --- +# --- PATCH: Record Python version and path --- +$pythonExe = (Get-Command python.exe).Source +$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts +$pythonVer = (& $pythonExe --version).Split()[1] + +$logDir = Join-Path $PSScriptRoot "logs" +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } +$verFile = Join-Path $logDir "python_version.txt" + +"Version=$pythonVer" | Out-File $verFile -Encoding ascii +"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append +# --- END PATCH --- + Stop-Transcript + exit 1 + } +} + +# Step 3: Ensure Python exists +function PythonExists { + (CmdExists "python") -or (CmdExists "py") -or (CmdExists "python3") +} + +if (-not (PythonExists)) { + Write-Host "Python not found. Attempting to install..." -ForegroundColor Yellow + if (CmdExists "winget") { + winget install -e --id Python.Python.3.12 + } elseif (CmdExists "choco") { + choco install python -y + } else { + try { + $PyInstaller = "$env:TEMP\PythonInstaller.exe" + Write-Host "Downloading Python installer..." -ForegroundColor Cyan + Invoke-WebRequest -Uri "https://www.python.org/ftp/python/3.12.6/python-3.12.6-amd64.exe" -OutFile $PyInstaller + Write-Host "Running Python installer silently..." -ForegroundColor Cyan + Start-Process -FilePath $PyInstaller -ArgumentList "/quiet","InstallAllUsers=1","PrependPath=1","Include_test=0" -Wait + } catch { + Write-Error "Python install failed. Please install manually: https://www.python.org/downloads/" +# --- PATCH BLOCK 1: Activation instructions --- +if ($env:ComSpec -like "*cmd.exe") { + $activation = ".\venv\Scripts\activate.bat" +} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { + $activation = ".\venv\Scripts\Activate.ps1" +} else { + $activation = "source venv/Scripts/activate" +} +Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green +Write-Host $activation -ForegroundColor Cyan + +# --- PATCH BLOCK 2: NSSM service setup --- +$nssmPath = "C:\nssm\nssm.exe" +if (-not (Test-Path $nssmPath)) { + try { + Write-Host "Downloading nssm..." -ForegroundColor Yellow + $nssmZip = Join-Path $env:TEMP "nssm.zip" + Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip + Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force + $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" + } catch { + Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." + $nssmPath = $null + } +} + +if ($nssmPath -and (Test-Path $nssmPath)) { + $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" + $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" + $appPath = Join-Path $TargetDir "app.py" + + Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow + & $nssmPath install RetroIPTVGuide $pythonExe $appPath + & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START + & $nssmPath start RetroIPTVGuide + Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green +} else { + Write-Warning "NSSM not available. Skipping service setup." +} +# --- END PATCH --- +# --- PATCH: Record Python version and path --- +$pythonExe = (Get-Command python.exe).Source +$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts +$pythonVer = (& $pythonExe --version).Split()[1] + +$logDir = Join-Path $PSScriptRoot "logs" +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } +$verFile = Join-Path $logDir "python_version.txt" + +"Version=$pythonVer" | Out-File $verFile -Encoding ascii +"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append +# --- END PATCH --- + Stop-Transcript + exit 1 + } + } +} + +# Step 4: Run RetroIPTVGuide installer under Git Bash (force cd into script root) +Write-Host "Running installer under Git Bash..." -ForegroundColor Cyan +& "$GitBashPath" -lc "cd '$PSScriptRoot' && git clone -b windows https://github.com/thehack904/RetroIPTVGuide.git && cd RetroIPTVGuide && chmod +x install.sh && ./install.sh" +# --- PATCH BLOCK 1: Activation instructions --- +if ($env:ComSpec -like "*cmd.exe") { + $activation = ".\venv\Scripts\activate.bat" +} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { + $activation = ".\venv\Scripts\Activate.ps1" +} else { + $activation = "source venv/Scripts/activate" +} +Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green +Write-Host $activation -ForegroundColor Cyan + +# --- PATCH BLOCK 2: NSSM service setup --- +$nssmPath = "C:\nssm\nssm.exe" +if (-not (Test-Path $nssmPath)) { + try { + Write-Host "Downloading nssm..." -ForegroundColor Yellow + $nssmZip = Join-Path $env:TEMP "nssm.zip" + Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip + Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force + $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" + } catch { + Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." + $nssmPath = $null + } +} + +if ($nssmPath -and (Test-Path $nssmPath)) { + $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" + $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" + $appPath = Join-Path $TargetDir "app.py" + + Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow + & $nssmPath install RetroIPTVGuide $pythonExe $appPath + & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START + & $nssmPath start RetroIPTVGuide + Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green +} else { + Write-Warning "NSSM not available. Skipping service setup." +} + +# --- PATCH: Open firewall port for RetroIPTVGuide --- +Write-Host "Opening Windows Firewall port 5000 for RetroIPTVGuide..." -ForegroundColor Yellow +netsh advfirewall firewall add rule name="RetroIPTVGuide" dir=in action=allow protocol=TCP localport=5000 | Out-Null + +# --- END PATCH --- +# --- PATCH: Record Python version and path --- +$pythonExe = (Get-Command python.exe).Source +$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts +$pythonVer = (& $pythonExe --version).Split()[1] + +$logDir = Join-Path $PSScriptRoot "logs" +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } +$verFile = Join-Path $logDir "python_version.txt" + +"Version=$pythonVer" | Out-File $verFile -Encoding ascii +"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append +# --- END PATCH --- +Stop-Transcript +Write-Host "Press any key to exit..." -ForegroundColor Cyan +Pause + +exit $LASTEXITCODE \ No newline at end of file diff --git a/uninstall.bat b/uninstall.bat new file mode 100644 index 0000000..9514868 --- /dev/null +++ b/uninstall.bat @@ -0,0 +1,2 @@ +@echo off +powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0uninstall_windows.ps1" diff --git a/uninstall_windows.ps1 b/uninstall_windows.ps1 new file mode 100644 index 0000000..1b6ea45 --- /dev/null +++ b/uninstall_windows.ps1 @@ -0,0 +1,322 @@ +<# uninstall_windows.ps1 + Complete uninstaller for RetroIPTVGuide + - Stops and removes Windows Service + - Removes RetroIPTVGuide repo + venv + - Removes Git Bash (if installed) + - Removes Python (if installed) + - Removes logs after transcript +#> + +$LogDir = Join-Path $PSScriptRoot "logs" +if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Force -Path $LogDir | Out-Null } +$TimeStamp = Get-Date -Format "yyyyMMdd_HHmmss" +$LogFile = Join-Path $LogDir "uninstall_$TimeStamp.log" + +Start-Transcript -Path $LogFile -Force + +# Elevation check +$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) +if (-not $IsAdmin) { + Write-Host "Re-launching with Administrator privileges..." -ForegroundColor Yellow +# --- PATCH: Corrected Python uninstall using version + path file --- +$pythonVerFile = Join-Path $PSScriptRoot "logs\python_version.txt" +if (Test-Path $pythonVerFile) { + $lines = Get-Content $pythonVerFile + $pythonVersion = ($lines | Where-Object { $_ -like "Version=*" }) -replace "Version=", "" + $pythonPath = ($lines | Where-Object { $_ -like "Path=*" }) -replace "Path=", "" + + Write-Host "Attempting to uninstall Python $pythonVersion from $pythonPath..." -ForegroundColor Yellow + + $uninstaller = Join-Path $pythonPath "uninstall.exe" + if (Test-Path $uninstaller) { + & $uninstaller /quiet | Out-Null + Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green + } else { + Write-Warning "Uninstaller not found at $uninstaller. Trying registry lookup..." + $uninstallKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" + $pythonKey = Get-ChildItem $uninstallKey | Where-Object { + $_.GetValue("DisplayName") -like "Python $pythonVersion*" + } | Select-Object -First 1 + if ($pythonKey) { + $uninstallString = $pythonKey.GetValue("UninstallString", $null) + if ($uninstallString) { + Write-Host "Running registry uninstall for Python $pythonVersion..." -ForegroundColor Yellow + & cmd.exe /c $uninstallString /quiet | Out-Null + Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green + } else { + Write-Warning "Registry entry found but no uninstall string for Python $pythonVersion." + } + } else { + Write-Warning "No registry entry found for Python $pythonVersion." + } + } +} else { + Write-Host "No python_version.txt found, falling back to existing uninstall logic..." -ForegroundColor Yellow +} +# --- END PATCH --- +# --- PATCH: Corrected Python uninstall with cleanup --- +$pythonVerFile = Join-Path $PSScriptRoot "logs\python_version.txt" +if (Test-Path $pythonVerFile) { + $lines = Get-Content $pythonVerFile + $pythonVersion = ($lines | Where-Object { $_ -like "Version=*" }) -replace "Version=", "" + $pythonPath = ($lines | Where-Object { $_ -like "Path=*" }) -replace "Path=", "" + + Write-Host "Attempting to uninstall Python $pythonVersion from $pythonPath..." -ForegroundColor Yellow + + $uninstaller = Join-Path $pythonPath "uninstall.exe" + if (Test-Path $uninstaller) { + & $uninstaller /quiet | Out-Null + Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green + } else { + Write-Warning "Uninstaller not found at $uninstaller. Trying registry lookup..." + $uninstallKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" + $pythonKey = Get-ChildItem $uninstallKey | Where-Object { + $_.GetValue("DisplayName") -like "Python $pythonVersion*" + } | Select-Object -First 1 + if ($pythonKey) { + $uninstallString = $pythonKey.GetValue("UninstallString", $null) + if ($uninstallString) { + Write-Host "Running registry uninstall for Python $pythonVersion..." -ForegroundColor Yellow + & cmd.exe /c $uninstallString /quiet | Out-Null + Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green + if (Test-Path $pythonPath) { + try { + Remove-Item -Recurse -Force $pythonPath + Write-Host "Removed leftover Python directory: $pythonPath" -ForegroundColor Green + } catch { + Write-Warning "Could not remove Python directory $pythonPath: $_" + } + } + } else { + Write-Warning "Registry entry found but no uninstall string for Python $pythonVersion." + } + } else { + Write-Warning "No registry entry found for Python $pythonVersion." + } + } +} else { + Write-Host "No python_version.txt found, falling back to existing uninstall logic..." -ForegroundColor Yellow +} +# --- END PATCH --- + Stop-Transcript + Start-Process -FilePath "powershell.exe" -Verb RunAs -ArgumentList "-ExecutionPolicy Bypass -File `"$PSCommandPath`"" + exit +} + +Write-Host "=== RetroIPTVGuide Complete Uninstaller ===" -ForegroundColor Cyan +Write-Host "Timestamp: $(Get-Date)" +Write-Host "Log file: $LogFile" + +# Stop and remove service +$service = Get-Service -Name "RetroIPTVGuide" -ErrorAction SilentlyContinue +if ($service) { + try { + if ($service.Status -eq "Running") { + Stop-Service -Name "RetroIPTVGuide" -Force + } + $nssmPath = "C:\nssm\nssm.exe" + if (Test-Path $nssmPath) { + & $nssmPath remove RetroIPTVGuide confirm + Write-Host "RetroIPTVGuide service removed." -ForegroundColor Green + } else { + sc.exe delete RetroIPTVGuide | Out-Null + Write-Host "RetroIPTVGuide service removed via sc.exe." -ForegroundColor Green + } + } catch { + Write-Warning "Could not remove RetroIPTVGuide service automatically." + } +} else { + Write-Host "RetroIPTVGuide service not found." -ForegroundColor Yellow +} + +# Candidate paths +$CandidateDirs = @( + (Join-Path $PSScriptRoot "RetroIPTVGuide"), + (Join-Path $env:USERPROFILE "RetroIPTVGuide"), + (Join-Path ($env:HOMEDRIVE + $env:HOMEPATH) "RetroIPTVGuide"), + (Join-Path $env:USERPROFILE "Desktop\RetroIPTVGuide"), + "C:\RetroIPTVGuide" +) + +foreach ($dir in $CandidateDirs) { + if (Test-Path $dir) { + try { + Remove-Item -Recurse -Force $dir + Write-Host "Removed RetroIPTVGuide folder: $dir" -ForegroundColor Green + break + } catch { + Write-Error "Failed to remove $dir" + } + } +} + +# Remove venv +$venvDirs = @( + (Join-Path $PSScriptRoot "venv"), + (Join-Path $env:USERPROFILE "venv"), + (Join-Path ($env:HOMEDRIVE + $env:HOMEPATH) "venv") +) +foreach ($vdir in $venvDirs) { + if (Test-Path $vdir) { + try { + Remove-Item -Recurse -Force $vdir + Write-Host "Removed venv: $vdir" -ForegroundColor Green + } catch { + Write-Error "Failed to remove venv: $vdir" + } + } +} + +# Attempt to remove Git Bash +$gitUninstall = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall" -ErrorAction SilentlyContinue | + Get-ItemProperty | Where-Object { $_.DisplayName -like "Git*" } +if ($gitUninstall -and $gitUninstall.UninstallString) { + try { + Start-Process -FilePath "cmd.exe" -ArgumentList "/c",$gitUninstall.UninstallString,"/VERYSILENT","/NORESTART" -Wait + Write-Host "Git Bash uninstalled." -ForegroundColor Green + } catch { + Write-Warning "Could not uninstall Git Bash automatically." + } +} else { + Write-Host "Git Bash not found." -ForegroundColor Yellow +} + +# Attempt to remove Python +$pyUninstall = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall" -ErrorAction SilentlyContinue | + Get-ItemProperty | Where-Object { $_.DisplayName -like "Python*" } +if ($pyUninstall -and $pyUninstall.UninstallString) { + try { + Start-Process -FilePath "cmd.exe" -ArgumentList "/c",$pyUninstall.UninstallString,"/quiet" -Wait + Write-Host "Python uninstalled." -ForegroundColor Green + } catch { + Write-Warning "Could not uninstall Python automatically." + } +} else { + Write-Host "Python not found." -ForegroundColor Yellow +} + +# --- PATCH: Stop and remove RetroIPTVGuide service, firewall rule, and NSSM --- +if (Get-Service RetroIPTVGuide -ErrorAction SilentlyContinue) { + Write-Host "Stopping RetroIPTVGuide service..." -ForegroundColor Yellow + Stop-Service RetroIPTVGuide -Force -ErrorAction SilentlyContinue +} + +$nssmPath = "C:\nssm\nssm.exe" +if (Test-Path $nssmPath) { + Write-Host "Removing RetroIPTVGuide service..." -ForegroundColor Yellow + & $nssmPath remove RetroIPTVGuide confirm +} + +Write-Host "Removing Windows Firewall port rule for RetroIPTVGuide..." -ForegroundColor Yellow +netsh advfirewall firewall delete rule name="RetroIPTVGuide" | Out-Null + +if (Test-Path "C:\nssm") { + Write-Host "Removing NSSM installation..." -ForegroundColor Yellow + Remove-Item -Recurse -Force "C:\nssm" +} + +# --- PATCH: Stop and remove RetroIPTVGuide service, firewall rule, and NSSM --- +if (Get-Service RetroIPTVGuide -ErrorAction SilentlyContinue) { + Write-Host "Stopping RetroIPTVGuide service..." -ForegroundColor Yellow + Stop-Service RetroIPTVGuide -Force -ErrorAction SilentlyContinue +} + +# Try NSSM first +$nssmPath = "C:\nssm\nssm.exe" +if (Test-Path $nssmPath) { + Write-Host "Removing RetroIPTVGuide service via NSSM..." -ForegroundColor Yellow + & $nssmPath remove RetroIPTVGuide confirm +} + +# Always try SC as a fallback to ensure service deletion +Write-Host "Ensuring RetroIPTVGuide service is deleted..." -ForegroundColor Yellow +sc.exe delete RetroIPTVGuide | Out-Null + +Write-Host "Removing Windows Firewall port rule for RetroIPTVGuide..." -ForegroundColor Yellow +netsh advfirewall firewall delete rule name="RetroIPTVGuide" | Out-Null + +if (Test-Path "C:\nssm") { + Write-Host "Removing NSSM installation..." -ForegroundColor Yellow + Remove-Item -Recurse -Force "C:\nssm" +} +# --- END PATCH --- + +# --- END PATCH --- +# --- PATCH: Python uninstall using version + path file --- +$pythonVerFile = Join-Path $PSScriptRoot "logs\python_version.txt" +if (Test-Path $pythonVerFile) { + $lines = Get-Content $pythonVerFile + $pythonVersion = ($lines | Where-Object { $_ -like "Version=*" }) -replace "Version=", "" + $pythonPath = ($lines | Where-Object { $_ -like "Path=*" }) -replace "Path=", "" + + Write-Host "Attempting to uninstall Python $pythonVersion from $pythonPath..." -ForegroundColor Yellow + + $uninstaller = Join-Path $pythonPath "uninstall.exe" + if (-not (Test-Path $uninstaller)) { + # fallback: use Modify/Repair entry in registry if uninstall.exe missing + $uninstallKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" + $pythonKey = Get-ChildItem $uninstallKey | Where-Object { + $_.GetValue("DisplayName") -like "Python $pythonVersion*" + } + if ($pythonKey) { + $uninstallString = $pythonKey.GetValue("UninstallString", $null) + if ($uninstallString) { + Write-Host "Running registry uninstall for Python $pythonVersion..." -ForegroundColor Yellow + & cmd.exe /c $uninstallString /quiet | Out-Null + } + } + } + +} else { + Write-Host "No python_version.txt found, falling back to existing uninstall logic..." -ForegroundColor Yellow +} +# --- END PATCH --- +# --- PATCH: Corrected Python uninstall using version + path file --- +$pythonVerFile = Join-Path $PSScriptRoot "logs\python_version.txt" +if (Test-Path $pythonVerFile) { + $lines = Get-Content $pythonVerFile + $pythonVersion = ($lines | Where-Object { $_ -like "Version=*" }) -replace "Version=", "" + $pythonPath = ($lines | Where-Object { $_ -like "Path=*" }) -replace "Path=", "" + + Write-Host "Attempting to uninstall Python $pythonVersion from $pythonPath..." -ForegroundColor Yellow + + $uninstaller = Join-Path $pythonPath "uninstall.exe" + if (Test-Path $uninstaller) { + & $uninstaller /quiet | Out-Null + Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green + } else { + Write-Warning "Uninstaller not found at $uninstaller. Trying registry lookup..." + $uninstallKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" + $pythonKey = Get-ChildItem $uninstallKey | Where-Object { + $_.GetValue("DisplayName") -like "Python $pythonVersion*" + } | Select-Object -First 1 + if ($pythonKey) { + $uninstallString = $pythonKey.GetValue("UninstallString", $null) + if ($uninstallString) { + Write-Host "Running registry uninstall for Python $pythonVersion..." -ForegroundColor Yellow + & cmd.exe /c $uninstallString /quiet | Out-Null + Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green + } else { + Write-Warning "Registry entry found but no uninstall string for Python $pythonVersion." + } + } else { + Write-Warning "No registry entry found for Python $pythonVersion." + } + } +} else { + Write-Host "No python_version.txt found, falling back to existing uninstall logic..." -ForegroundColor Yellow +} +# --- END PATCH --- +Stop-Transcript +Write-Host "Press any key to exit..." -ForegroundColor Cyan +Pause + +# Clean logs after transcript ends +#if (Test-Path $LogDir) { +# try { +# Remove-Item -Recurse -Force $LogDir +# Write-Host "Removed logs folder: $LogDir" -ForegroundColor Green +# } catch { +# Write-Warning "Failed to remove logs folder: $LogDir" +# } +#} From 32617e619945c7079b374c6d0c4f6cef9bbb16fe Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Fri, 3 Oct 2025 20:56:50 -0500 Subject: [PATCH 3/5] Windows_ALPHA --- install.sh | 138 +++++++- install_windows.ps1 | 756 ++++++++++++++---------------------------- uninstall_windows.ps1 | 427 ++++++++---------------- 3 files changed, 540 insertions(+), 781 deletions(-) diff --git a/install.sh b/install.sh index 248d244..8aeecbf 100644 --- a/install.sh +++ b/install.sh @@ -1,3 +1,31 @@ +#!/bin/bash +set -e + +VERSION="2.1.0" +TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") +LOGFILE="install_${TIMESTAMP}.log" + +# Log everything to file + console +exec > >(tee -a "$LOGFILE") 2>&1 + +echo "=== RetroIPTVGuide Installer (v$VERSION) ===" +echo "Start time: $(date)" +echo "Log file: $LOGFILE" + +# --- Detect Environment --- +if grep -qi microsoft /proc/version 2>/dev/null; then + ENVIRONMENT="WSL" +elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]]; then + ENVIRONMENT="GITBASH" +elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + ENVIRONMENT="LINUX" +else + ENVIRONMENT="UNKNOWN" +fi + +echo "Detected environment: $ENVIRONMENT" + +windows_install() { #!/usr/bin/env bash # install.sh - Installer for RetroIPTVGuide # Detects environment, creates venv, ensures pip is up-to-date only if needed. @@ -53,9 +81,113 @@ fi # Install requirements $PYTHON_BIN -m pip install -r requirements.txt -echo "=== Installation complete. Activate venv with ===" +} + + +linux_install(){ +# Ensure script is run with sudo on Linux/WSL +if [[ "$ENVIRONMENT" == "LINUX" || "$ENVIRONMENT" == "WSL" ]]; then + if [[ $EUID -ne 0 ]]; then + echo "This script must be run with sudo." + exit 1 + fi +fi + +# Variables +APP_USER="iptv" +APP_HOME="/home/$APP_USER" +APP_DIR="$APP_HOME/iptv-server" +SERVICE_FILE="/etc/systemd/system/iptv-server.service" + +# --- Linux/WSL Install Path --- +if [[ "$ENVIRONMENT" == "LINUX" || "$ENVIRONMENT" == "WSL" ]]; then + # Create system user if not exists + if id "$APP_USER" &>/dev/null; then + echo "User $APP_USER already exists." + else + echo "Creating iptv system user..." + adduser --system --home "$APP_HOME" --group "$APP_USER" + fi + + # Ensure python3-venv is installed + echo "Checking for python3-venv..." + if ! dpkg -s python3-venv >/dev/null 2>&1; then + echo "python3-venv not found. Installing..." + apt-get update + apt-get install -y python3-venv + else + echo "python3-venv is already installed." + fi + + # Create app directory + mkdir -p "$APP_DIR" + chown -R $APP_USER:$APP_USER "$APP_HOME" + + # Copy project files + echo "Copying project files..." + rsync -a --exclude 'venv' ./ "$APP_DIR/" + chown -R $APP_USER:$APP_USER "$APP_DIR" + + # Setup virtual environment + cd "$APP_DIR" + echo "Setting up Python virtual environment..." + sudo -u $APP_USER python3 -m venv venv + + echo "Upgrading pip..." + sudo -u $APP_USER $APP_DIR/venv/bin/pip install --upgrade pip + + echo "Installing requirements..." + sudo -u $APP_USER $APP_DIR/venv/bin/pip install -r "$APP_DIR/requirements.txt" + + # Create systemd service + echo "Creating systemd service..." + cat > "$SERVICE_FILE" </dev/null 2>&1; then + echo "Error: Python not found in PATH. Please install Python 3 manually." + exit 1 + fi + echo "Setting up Python virtual environment..." + python -m venv venv + source venv/Scripts/activate + echo "Upgrading pip..." + pip install --upgrade pip + echo "Installing requirements..." + pip install -r requirements.txt + echo "Starting RetroIPTVGuide in development mode..." + python app.py & +else + echo "Unsupported environment: $OSTYPE" + exit 1 +fi +} + if [ "$ENVIRONMENT" = "GITBASH" ]; then - echo "source venv/Scripts/activate" + windows_install else - echo "source venv/bin/activate" + linux_install fi diff --git a/install_windows.ps1 b/install_windows.ps1 index 4447c95..96bd916 100644 --- a/install_windows.ps1 +++ b/install_windows.ps1 @@ -1,19 +1,17 @@ -<# install_windows.ps1 - Windows bootstrap for RetroIPTVGuide - - Prefer WSL if installed - - Else fallback to Git Bash - - Check/install Git + Python if missing - - Force Git Bash to cd into script root before cloning - - All output logged to file +<# +RetroIPTVGuide Windows Installer +Clean version with only prerequisite checks and service setup #> -$LogDir = Join-Path $PSScriptRoot "logs" -if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Force -Path $LogDir | Out-Null } -$TimeStamp = Get-Date -Format "yyyyMMdd_HHmmss" -$LogFile = Join-Path $LogDir "install_$TimeStamp.log" - -Start-Transcript -Path $LogFile -Force +# === Start Transcript === +$logDir = "$PSScriptRoot\logs" +if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Force -Path $logDir | Out-Null } +$logFile = Join-Path $logDir ("install_{0:yyyyMMdd_HHmmss}.log" -f (Get-Date)) +Start-Transcript -Path $logFile -Append +Write-Host "=== RetroIPTVGuide Windows Installer ===" -ForegroundColor Cyan +Write-Host "Log file: $logFile" -ForegroundColor Gray +# --- Ensure Admin Privileges --- # Elevation check $IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $IsAdmin) { @@ -23,536 +21,298 @@ if (-not $IsAdmin) { exit } -Write-Host "=== RetroIPTVGuide Windows Installer Bootstrap ===" -ForegroundColor Cyan -Write-Host "Timestamp: $(Get-Date)" -Write-Host "Log file: $LogFile" -Write-Host "OS: $([System.Environment]::OSVersion.VersionString)" - -# Elevation check -$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") -if (-not $IsAdmin) { - Write-Host "Re-launching with Administrator privileges..." -ForegroundColor Yellow -# --- PATCH BLOCK 1: Activation instructions --- -if ($env:ComSpec -like "*cmd.exe") { - $activation = ".\venv\Scripts\activate.bat" -} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { - $activation = ".\venv\Scripts\Activate.ps1" -} else { - $activation = "source venv/Scripts/activate" -} -Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green -Write-Host $activation -ForegroundColor Cyan - -# --- PATCH BLOCK 2: NSSM service setup --- -$nssmPath = "C:\nssm\nssm.exe" -if (-not (Test-Path $nssmPath)) { - try { - Write-Host "Downloading nssm..." -ForegroundColor Yellow - $nssmZip = Join-Path $env:TEMP "nssm.zip" - Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip - Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force - $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" - } catch { - Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." - $nssmPath = $null - } +Write-Host "" +Write-Host "============================================================" -ForegroundColor Yellow +Write-Host " RetroIPTVGuide Installer Agreement " -ForegroundColor Cyan +Write-Host "============================================================" -ForegroundColor Yellow +Write-Host "" +Write-Host "This installer will perform the following actions:" -ForegroundColor White +Write-Output " - Bootstraps / Installs Chocolatey" +Write-Output " - Installs dependencies: python, git, nssm" +Write-Output " - Registers Windows App Paths for python/python3" +Write-Output " - Adds Python to Git Bash (~/.bashrc)" +Write-Output " - Clones RetroIPTVGuide into the same folder as the installer" +Write-Output " - Runs install.sh via Git Bash" +Write-Output " - Creates an NSSM service to run venv\\Scripts\\python.exe app.py" +Write-Output " - Open Windows Firewall port 5000 for RetroIPTVGuide Service" +Write-Output " - Starts the RetroIPTVGuide service" +Write-Host "" +Write-Host "By continuing, you acknowledge and agree that:" -ForegroundColor White +Write-Output " - This software should ONLY be run on internal networks." +Write-Output " - It must NOT be exposed to the public Internet." +Write-Output " - You accept all risks; the author provides NO WARRANTY." +Write-Output " - The author is NOT responsible for any damage, data loss," +Write-Output " or security vulnerabilities created by this installation." +Write-Host "" +Write-Host "Do you agree to these terms? (yes/no)" -ForegroundColor Yellow + +$agreement = Read-Host "Type yes or no" +Write-Output "User response to agreement: $agreement" + +if ($agreement.ToLower() -ne "yes") { + Write-Host "Installation aborted by user." -ForegroundColor Red + Stop-Transcript + exit 1 } -if ($nssmPath -and (Test-Path $nssmPath)) { - $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" - $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" - $appPath = Join-Path $TargetDir "app.py" - - Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow - & $nssmPath install RetroIPTVGuide $pythonExe $appPath - & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START - & $nssmPath start RetroIPTVGuide - Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green -} else { - Write-Warning "NSSM not available. Skipping service setup." -} -# --- END PATCH --- -# --- PATCH: Record Python version and path --- -$pythonExe = (Get-Command python.exe).Source -$pythonDir = Split-Path $pythonExe -Parent # <-- this gives Scripts -$pythonRoot = Split-Path $pythonDir -Parent # <-- this gives Python312 folder -$pythonVer = (& $pythonExe --version).Split()[1] - -$logDir = Join-Path $PSScriptRoot "logs" -if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } -$verFile = Join-Path $logDir "python_version.txt" - -"Version=$pythonVer" | Out-File $verFile -Encoding ascii -"Path=$pythonRoot" | Out-File $verFile -Encoding ascii -Append -# --- END PATCH --- - Stop-Transcript - Start-Process -FilePath "powershell.exe" -Verb RunAs -ArgumentList "-NoProfile","-ExecutionPolicy","Bypass","-File","`"$PSCommandPath`"" - exit +# --- Chocolatey --- +Write-Host "Checking for Chocolatey..." -ForegroundColor Cyan +$choco = Get-Command choco -ErrorAction SilentlyContinue +if (-not $choco) { + Write-Host "Installing Chocolatey..." -ForegroundColor Yellow + Set-ExecutionPolicy Bypass -Scope Process -Force + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") } -function CmdExists($name) { Get-Command $name -ErrorAction SilentlyContinue | Out-Null } - -# Step 1: Prefer WSL -$HasWslExe = CmdExists "wsl.exe" -if ($HasWslExe) { - $distros = & wsl.exe -l -q 2>$null - if ($LASTEXITCODE -eq 0 -and $distros -and $distros.Trim().Length -gt 0) { - Write-Host "WSL distribution detected. Installing inside WSL..." -ForegroundColor Cyan - wsl.exe -- bash -lc "git clone -b windows https://github.com/thehack904/RetroIPTVGuide.git && cd RetroIPTVGuide && chmod +x install.sh && ./install.sh" -# --- PATCH BLOCK 1: Activation instructions --- -if ($env:ComSpec -like "*cmd.exe") { - $activation = ".\venv\Scripts\activate.bat" -} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { - $activation = ".\venv\Scripts\Activate.ps1" +# --- Python --- +Write-Host "Checking for Python..." -ForegroundColor Cyan +if (choco list | Select-String -Pattern "^python3 ") { + Write-Host "Python3 is installed" } else { - $activation = "source venv/Scripts/activate" + Write-Host "Python3 not found, installing..." + choco install python3 -y } -Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green -Write-Host $activation -ForegroundColor Cyan - -# --- PATCH BLOCK 2: NSSM service setup --- -$nssmPath = "C:\nssm\nssm.exe" -if (-not (Test-Path $nssmPath)) { - try { - Write-Host "Downloading nssm..." -ForegroundColor Yellow - $nssmZip = Join-Path $env:TEMP "nssm.zip" - Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip - Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force - $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" - } catch { - Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." - $nssmPath = $null + +# --- Fix Python alias stubs from Microsoft Store --- +$aliases = @( + "$env:LOCALAPPDATA\Microsoft\WindowsApps\python.exe", + "$env:LOCALAPPDATA\Microsoft\WindowsApps\python3.exe", + "$env:LOCALAPPDATA\Microsoft\WindowsApps\python3.*.exe" +) + +foreach ($alias in $aliases) { + if (Test-Path $alias) { + try { + Remove-Item $alias -Force + Write-Host "Removed Microsoft Store alias: $alias" -ForegroundColor Yellow + } catch { + Write-Warning "Failed to remove alias ${alias}: $_" + } } } -if ($nssmPath -and (Test-Path $nssmPath)) { - $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" - $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" - $appPath = Join-Path $TargetDir "app.py" +# --- Ensure Chocolatey shims directory comes first in PATH --- +$chocoBin = "C:\ProgramData\chocolatey\bin" +$currentPath = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") - Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow - & $nssmPath install RetroIPTVGuide $pythonExe $appPath - & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START - & $nssmPath start RetroIPTVGuide - Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green -} else { - Write-Warning "NSSM not available. Skipping service setup." -} -# --- END PATCH --- -# --- PATCH: Record Python version and path --- -$pythonExe = (Get-Command python.exe).Source -$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts -$pythonVer = (& $pythonExe --version).Split()[1] - -$logDir = Join-Path $PSScriptRoot "logs" -if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } -$verFile = Join-Path $logDir "python_version.txt" - -"Version=$pythonVer" | Out-File $verFile -Encoding ascii -"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append -# --- END PATCH --- - Stop-Transcript - exit $LASTEXITCODE - } else { - Write-Host "WSL present but no Linux distro installed." -ForegroundColor Yellow - try { - wsl.exe --install -d Ubuntu - Write-Host "Ubuntu installation initiated. Please reboot when prompted, then re-run this script." -ForegroundColor Green -# --- PATCH BLOCK 1: Activation instructions --- -if ($env:ComSpec -like "*cmd.exe") { - $activation = ".\venv\Scripts\activate.bat" -} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { - $activation = ".\venv\Scripts\Activate.ps1" +if (-not ($currentPath -split ";" | ForEach-Object { $_.Trim() } | Where-Object { $_ -eq $chocoBin })) { + $newPath = "$chocoBin;$currentPath" + [System.Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine") + Write-Host "Updated PATH to prioritize Chocolatey bin: $chocoBin" -ForegroundColor Green } else { - $activation = "source venv/Scripts/activate" + Write-Host "Chocolatey bin already in PATH." -ForegroundColor Green } -Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green -Write-Host $activation -ForegroundColor Cyan - -# --- PATCH BLOCK 2: NSSM service setup --- -$nssmPath = "C:\nssm\nssm.exe" -if (-not (Test-Path $nssmPath)) { - try { - Write-Host "Downloading nssm..." -ForegroundColor Yellow - $nssmZip = Join-Path $env:TEMP "nssm.zip" - Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip - Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force - $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" - } catch { - Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." - $nssmPath = $null + +# --- Add registry App Paths aliases for python/python3 --- +try { + $pythonExe = (Get-Command python.exe -ErrorAction SilentlyContinue).Source + if (-not $pythonExe) { + $pythonExe = "C:\Python313\python.exe" # fallback if not resolved via PATH } -} -if ($nssmPath -and (Test-Path $nssmPath)) { - $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" - $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" - $appPath = Join-Path $TargetDir "app.py" + if (Test-Path $pythonExe) { + New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\python.exe" -Force | Out-Null + Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\python.exe" -Name "(Default)" -Value $pythonExe - Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow - & $nssmPath install RetroIPTVGuide $pythonExe $appPath - & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START - & $nssmPath start RetroIPTVGuide - Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green -} else { - Write-Warning "NSSM not available. Skipping service setup." -} -# --- END PATCH --- -# --- PATCH: Record Python version and path --- -$pythonExe = (Get-Command python.exe).Source -$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts -$pythonVer = (& $pythonExe --version).Split()[1] - -$logDir = Join-Path $PSScriptRoot "logs" -if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } -$verFile = Join-Path $logDir "python_version.txt" - -"Version=$pythonVer" | Out-File $verFile -Encoding ascii -"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append -# --- END PATCH --- - Stop-Transcript - exit 0 - } catch { - Write-Warning "Automatic WSL install failed. Install WSL manually, then rerun." -# --- PATCH BLOCK 1: Activation instructions --- -if ($env:ComSpec -like "*cmd.exe") { - $activation = ".\venv\Scripts\activate.bat" -} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { - $activation = ".\venv\Scripts\Activate.ps1" -} else { - $activation = "source venv/Scripts/activate" -} -Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green -Write-Host $activation -ForegroundColor Cyan - -# --- PATCH BLOCK 2: NSSM service setup --- -$nssmPath = "C:\nssm\nssm.exe" -if (-not (Test-Path $nssmPath)) { - try { - Write-Host "Downloading nssm..." -ForegroundColor Yellow - $nssmZip = Join-Path $env:TEMP "nssm.zip" - Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip - Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force - $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" - } catch { - Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." - $nssmPath = $null + New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\python3.exe" -Force | Out-Null + Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\python3.exe" -Name "(Default)" -Value $pythonExe + + Write-Host "Registered App Path aliases: python, python3 -> $pythonExe" -ForegroundColor Green + } else { + Write-Warning "Python executable not found for alias registration." } +} catch { + Write-Warning "Failed to register python/python3 aliases in App Paths: $_" } -if ($nssmPath -and (Test-Path $nssmPath)) { - $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" - $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" - $appPath = Join-Path $TargetDir "app.py" - Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow - & $nssmPath install RetroIPTVGuide $pythonExe $appPath - & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START - & $nssmPath start RetroIPTVGuide - Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green +# --- Ensure Chocolatey is installed --- +if (-not (Get-Command choco.exe -ErrorAction SilentlyContinue)) { + Write-Host "Installing Chocolatey..." -ForegroundColor Cyan + Set-ExecutionPolicy Bypass -Scope Process -Force + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) } else { - Write-Warning "NSSM not available. Skipping service setup." -} -# --- END PATCH --- -# --- PATCH: Record Python version and path --- -$pythonExe = (Get-Command python.exe).Source -$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts -$pythonVer = (& $pythonExe --version).Split()[1] - -$logDir = Join-Path $PSScriptRoot "logs" -if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } -$verFile = Join-Path $logDir "python_version.txt" - -"Version=$pythonVer" | Out-File $verFile -Encoding ascii -"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append -# --- END PATCH --- - Stop-Transcript - exit 1 - } - } + Write-Host "Chocolatey already installed." -ForegroundColor Green } -# Step 2: Fallback to Git Bash -Write-Host "WSL not available. Falling back to Git Bash..." -ForegroundColor Yellow -$GitBashPath = "$Env:ProgramFiles\Git\bin\bash.exe" -if (-not (Test-Path $GitBashPath)) { $GitBashPath = "$Env:ProgramFiles(x86)\Git\bin\bash.exe" } - -if (-not (Test-Path $GitBashPath)) { - Write-Host "Git for Windows not found. Attempting to install..." -ForegroundColor Yellow - - if (CmdExists "winget") { - winget install -e --id Git.Git --silent - } elseif (CmdExists "choco") { - choco install git -y - } else { - # Fallback: direct download + silent install - try { - $Installer = "$env:TEMP\GitInstaller.exe" - Write-Host "Downloading Git for Windows installer..." -ForegroundColor Cyan - Invoke-WebRequest -Uri "https://github.com/git-for-windows/git/releases/download/v2.47.0.windows.1/Git-2.47.0-64-bit.exe" -OutFile $Installer - Write-Host "Running Git installer silently..." -ForegroundColor Cyan - Start-Process -FilePath $Installer -ArgumentList "/VERYSILENT","/NORESTART" -Wait - } catch { - Write-Error "Automatic Git install failed. Please install Git manually: https://git-scm.com/download/win" -# --- PATCH BLOCK 1: Activation instructions --- -if ($env:ComSpec -like "*cmd.exe") { - $activation = ".\venv\Scripts\activate.bat" -} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { - $activation = ".\venv\Scripts\Activate.ps1" -} else { - $activation = "source venv/Scripts/activate" -} -Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green -Write-Host $activation -ForegroundColor Cyan - -# --- PATCH BLOCK 2: NSSM service setup --- -$nssmPath = "C:\nssm\nssm.exe" -if (-not (Test-Path $nssmPath)) { - try { - Write-Host "Downloading nssm..." -ForegroundColor Yellow - $nssmZip = Join-Path $env:TEMP "nssm.zip" - Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip - Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force - $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" - } catch { - Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." - $nssmPath = $null +# --- Ensure dependencies --- +$packages = @("python3", "nssm", "git") + +foreach ($pkg in $packages) { + $installed = choco list --limit-output | Select-String -Pattern "^$pkg " + if (-not $installed) { + Write-Host "Installing $pkg..." -ForegroundColor Cyan + choco install $pkg -y | Out-Null + } else { + Write-Host "$pkg already installed." -ForegroundColor Green } } -if ($nssmPath -and (Test-Path $nssmPath)) { - $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" - $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" - $appPath = Join-Path $TargetDir "app.py" +Write-Host "All dependencies installed." -ForegroundColor Green - Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow - & $nssmPath install RetroIPTVGuide $pythonExe $appPath - & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START - & $nssmPath start RetroIPTVGuide - Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green -} else { - Write-Warning "NSSM not available. Skipping service setup." -} -# --- END PATCH --- -# --- PATCH: Record Python version and path --- -$pythonExe = (Get-Command python.exe).Source -$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts -$pythonVer = (& $pythonExe --version).Split()[1] - -$logDir = Join-Path $PSScriptRoot "logs" -if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } -$verFile = Join-Path $logDir "python_version.txt" - -"Version=$pythonVer" | Out-File $verFile -Encoding ascii -"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append -# --- END PATCH --- - Stop-Transcript - exit 1 +# --- Ensure Python aliases point to correct installed version --- +try { + $pythonExePath = (Get-Command python3.exe -ErrorAction SilentlyContinue).Source + if (-not $pythonExePath) { + $pythonExePath = (Get-Command python.exe -ErrorAction SilentlyContinue).Source } - } - - # Re-check after install - $GitBashPath = "$Env:ProgramFiles\Git\bin\bash.exe" - if (-not (Test-Path $GitBashPath)) { $GitBashPath = "$Env:ProgramFiles(x86)\Git\bin\bash.exe" } - if (-not (Test-Path $GitBashPath)) { - Write-Error "Git Bash still not found after install attempt." -# --- PATCH BLOCK 1: Activation instructions --- -if ($env:ComSpec -like "*cmd.exe") { - $activation = ".\venv\Scripts\activate.bat" -} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { - $activation = ".\venv\Scripts\Activate.ps1" -} else { - $activation = "source venv/Scripts/activate" + + if ($pythonExePath) { + Write-Host "Found Python executable at $pythonExePath" -ForegroundColor Cyan + + # Persist App Path so Windows resolves python/python3 correctly + $aliases = @("python.exe", "python3.exe") + foreach ($alias in $aliases) { + $regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\$alias" + if (-not (Test-Path $regPath)) { + New-Item -Path $regPath -Force | Out-Null + } + Set-ItemProperty -Path $regPath -Name "(Default)" -Value $pythonExePath + Set-ItemProperty -Path $regPath -Name "Path" -Value (Split-Path $pythonExePath) + } + + Write-Host "Registered App Path aliases: python, python3 -> $pythonExePath" -ForegroundColor Green + } else { + Write-Warning "Python executable not found in PATH. Aliases not created." + } +} catch { + Write-Warning "Failed to configure Python aliases: $_" } -Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green -Write-Host $activation -ForegroundColor Cyan - -# --- PATCH BLOCK 2: NSSM service setup --- -$nssmPath = "C:\nssm\nssm.exe" -if (-not (Test-Path $nssmPath)) { - try { - Write-Host "Downloading nssm..." -ForegroundColor Yellow - $nssmZip = Join-Path $env:TEMP "nssm.zip" - Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip - Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force - $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" - } catch { - Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." - $nssmPath = $null + +# --- Ensure Python aliases point to correct installed version --- +try { + # Look up Python installation folder from Chocolatey + $pythonPkg = choco list | Select-String -Pattern "^python3 " + if ($pythonPkg) { + # Most choco python3 installs under C:\Python3xx + $pythonDir = Get-ChildItem "C:\Python*" -Directory | Sort-Object LastWriteTime -Descending | Select-Object -First 1 + $pythonExePath = Join-Path $pythonDir.FullName "python.exe" + + if (Test-Path $pythonExePath) { + Write-Host "Found Python executable at $pythonExePath" -ForegroundColor Cyan + + # Persist App Path so Windows resolves python/python3 correctly + $aliases = @("python.exe", "python3.exe") + foreach ($alias in $aliases) { + $regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\$alias" + if (-not (Test-Path $regPath)) { + New-Item -Path $regPath -Force | Out-Null + } + Set-ItemProperty -Path $regPath -Name "(Default)" -Value $pythonExePath + Set-ItemProperty -Path $regPath -Name "Path" -Value $pythonDir.FullName + } + + Write-Host "Registered App Path aliases: python, python3 -> $pythonExePath" -ForegroundColor Green + + # --- Add Python to Git Bash PATH via ~/.bashrc --- + $gitBashHome = Join-Path $env:USERPROFILE ".bashrc" + $bashrcLine = "export PATH=""/c/$($pythonDir.Name):/c/$($pythonDir.Name)/Scripts:`$PATH""" + + if (Test-Path $gitBashHome) { + if (-not (Select-String -Path $gitBashHome -Pattern $pythonDir.Name -Quiet)) { + Add-Content -Path $gitBashHome -Value $bashrcLine + Write-Host "Added Python to Git Bash PATH in .bashrc" -ForegroundColor Yellow + } + } else { + Set-Content -Path $gitBashHome -Value $bashrcLine + Write-Host "Created .bashrc and added Python PATH for Git Bash" -ForegroundColor Yellow + } + + } else { + Write-Warning "Python executable not found in expected location." + } + } else { + Write-Warning "Python not installed by Chocolatey, skipping alias setup." } +} catch { + Write-Warning "Failed to configure Python aliases: $_" } -if ($nssmPath -and (Test-Path $nssmPath)) { - $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" - $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" - $appPath = Join-Path $TargetDir "app.py" - Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow - & $nssmPath install RetroIPTVGuide $pythonExe $appPath - & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START - & $nssmPath start RetroIPTVGuide - Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green -} else { - Write-Warning "NSSM not available. Skipping service setup." -} -# --- END PATCH --- -# --- PATCH: Record Python version and path --- -$pythonExe = (Get-Command python.exe).Source -$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts -$pythonVer = (& $pythonExe --version).Split()[1] - -$logDir = Join-Path $PSScriptRoot "logs" -if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } -$verFile = Join-Path $logDir "python_version.txt" - -"Version=$pythonVer" | Out-File $verFile -Encoding ascii -"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append -# --- END PATCH --- - Stop-Transcript - exit 1 - } -} -# Step 3: Ensure Python exists -function PythonExists { - (CmdExists "python") -or (CmdExists "py") -or (CmdExists "python3") -} -if (-not (PythonExists)) { - Write-Host "Python not found. Attempting to install..." -ForegroundColor Yellow - if (CmdExists "winget") { - winget install -e --id Python.Python.3.12 - } elseif (CmdExists "choco") { - choco install python -y - } else { - try { - $PyInstaller = "$env:TEMP\PythonInstaller.exe" - Write-Host "Downloading Python installer..." -ForegroundColor Cyan - Invoke-WebRequest -Uri "https://www.python.org/ftp/python/3.12.6/python-3.12.6-amd64.exe" -OutFile $PyInstaller - Write-Host "Running Python installer silently..." -ForegroundColor Cyan - Start-Process -FilePath $PyInstaller -ArgumentList "/quiet","InstallAllUsers=1","PrependPath=1","Include_test=0" -Wait - } catch { - Write-Error "Python install failed. Please install manually: https://www.python.org/downloads/" -# --- PATCH BLOCK 1: Activation instructions --- -if ($env:ComSpec -like "*cmd.exe") { - $activation = ".\venv\Scripts\activate.bat" -} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { - $activation = ".\venv\Scripts\Activate.ps1" -} else { - $activation = "source venv/Scripts/activate" -} -Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green -Write-Host $activation -ForegroundColor Cyan - -# --- PATCH BLOCK 2: NSSM service setup --- -$nssmPath = "C:\nssm\nssm.exe" -if (-not (Test-Path $nssmPath)) { - try { - Write-Host "Downloading nssm..." -ForegroundColor Yellow - $nssmZip = Join-Path $env:TEMP "nssm.zip" - Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip - Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force - $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" - } catch { - Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." - $nssmPath = $null - } -} -if ($nssmPath -and (Test-Path $nssmPath)) { - $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" - $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" - $appPath = Join-Path $TargetDir "app.py" +# --- Clone RetroIPTVGuide --- +$installDir = "$PSScriptRoot\RetroIPTVGuide" +if (Test-Path $installDir) { Remove-Item -Recurse -Force $installDir } +# Resolve Git path +$gitExe = (Get-Command git.exe -ErrorAction SilentlyContinue).Source +if (-not $gitExe) { $gitExe = "C:\Program Files\Git\bin\git.exe" } +if (-not (Test-Path $gitExe)) { $gitExe = "C:\Program Files (x86)\Git\bin\git.exe" } - Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow - & $nssmPath install RetroIPTVGuide $pythonExe $appPath - & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START - & $nssmPath start RetroIPTVGuide - Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green -} else { - Write-Warning "NSSM not available. Skipping service setup." -} -# --- END PATCH --- -# --- PATCH: Record Python version and path --- -$pythonExe = (Get-Command python.exe).Source -$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts -$pythonVer = (& $pythonExe --version).Split()[1] - -$logDir = Join-Path $PSScriptRoot "logs" -if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } -$verFile = Join-Path $logDir "python_version.txt" - -"Version=$pythonVer" | Out-File $verFile -Encoding ascii -"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append -# --- END PATCH --- - Stop-Transcript - exit 1 - } - } +if (-not (Test-Path $gitExe)) { + Write-Error "Git executable not found even after installation. Please verify Git installation." + exit 1 } -# Step 4: Run RetroIPTVGuide installer under Git Bash (force cd into script root) -Write-Host "Running installer under Git Bash..." -ForegroundColor Cyan -& "$GitBashPath" -lc "cd '$PSScriptRoot' && git clone -b windows https://github.com/thehack904/RetroIPTVGuide.git && cd RetroIPTVGuide && chmod +x install.sh && ./install.sh" -# --- PATCH BLOCK 1: Activation instructions --- -if ($env:ComSpec -like "*cmd.exe") { - $activation = ".\venv\Scripts\activate.bat" -} elseif ($PSVersionTable.PSEdition -eq "Core" -or $host.Name -like "*PowerShell*") { - $activation = ".\venv\Scripts\Activate.ps1" -} else { - $activation = "source venv/Scripts/activate" -} -Write-Host "=== Installation complete. Activate venv with ===" -ForegroundColor Green -Write-Host $activation -ForegroundColor Cyan - -# --- PATCH BLOCK 2: NSSM service setup --- -$nssmPath = "C:\nssm\nssm.exe" -if (-not (Test-Path $nssmPath)) { - try { - Write-Host "Downloading nssm..." -ForegroundColor Yellow - $nssmZip = Join-Path $env:TEMP "nssm.zip" - Invoke-WebRequest -Uri "https://nssm.cc/release/nssm-2.24.zip" -OutFile $nssmZip - Expand-Archive $nssmZip -DestinationPath "C:\nssm" -Force - $nssmPath = "C:\nssm\nssm-2.24\win64\nssm.exe" - } catch { - Write-Warning "Failed to download/extract nssm automatically. Install from https://nssm.cc/ and rerun service setup." - $nssmPath = $null +# Clone the repository +#& $gitExe clone -b windows https://github.com/thehack904/RetroIPTVGuide.git $installDir + +# --- Run install.sh using Git Bash --- +try { + $gitBash = "C:\Program Files\Git\bin\bash.exe" + #$repoDir = Join-Path $PSScriptRoot "RetroIPTVGuide" + $repoDir = $PSScriptRoot + + if (Test-Path $gitBash -PathType Leaf) { + if (Test-Path (Join-Path $repoDir "install.sh")) { + Write-Host "Running install.sh with Git Bash..." -ForegroundColor Cyan + & "$gitBash" --login -i -c "cd '$repoDir' && chmod +x install.sh && ./install.sh" + } else { + Write-Warning "install.sh not found in $repoDir" + } + } else { + Write-Warning "Git Bash not found at $gitBash. Skipping install.sh" } -} - -if ($nssmPath -and (Test-Path $nssmPath)) { - $TargetDir = Join-Path $PSScriptRoot "RetroIPTVGuide" - $pythonExe = Join-Path $TargetDir "venv\Scripts\python.exe" - $appPath = Join-Path $TargetDir "app.py" - - Write-Host "Setting up RetroIPTVGuide Windows Service..." -ForegroundColor Yellow - & $nssmPath install RetroIPTVGuide $pythonExe $appPath - & $nssmPath set RetroIPTVGuide Start SERVICE_AUTO_START - & $nssmPath start RetroIPTVGuide - Write-Host "RetroIPTVGuide service installed and started." -ForegroundColor Green -} else { - Write-Warning "NSSM not available. Skipping service setup." +} catch { + Write-Warning "Failed to run install.sh in Git Bash: $_" } # --- PATCH: Open firewall port for RetroIPTVGuide --- Write-Host "Opening Windows Firewall port 5000 for RetroIPTVGuide..." -ForegroundColor Yellow netsh advfirewall firewall add rule name="RetroIPTVGuide" dir=in action=allow protocol=TCP localport=5000 | Out-Null -# --- END PATCH --- -# --- PATCH: Record Python version and path --- -$pythonExe = (Get-Command python.exe).Source -$pythonDir = Split-Path (Split-Path $pythonExe -Parent) -Parent # parent folder of Scripts -$pythonVer = (& $pythonExe --version).Split()[1] +# --- Configure NSSM service for RetroIPTVGuide --- +try { + $nssm = "C:\ProgramData\chocolatey\bin\nssm.exe" + #$repoDir = Join-Path $PSScriptRoot "RetroIPTVGuide" + $repoDir = $PSScriptRoot + $venvPython = Join-Path $repoDir "venv\Scripts\python.exe" + $appPy = Join-Path $repoDir "app.py" -$logDir = Join-Path $PSScriptRoot "logs" -if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir | Out-Null } -$verFile = Join-Path $logDir "python_version.txt" + if ((Test-Path $nssm -PathType Leaf) -and (Test-Path $venvPython) -and (Test-Path $appPy)) { + Write-Host "Setting up NSSM service for RetroIPTVGuide..." -ForegroundColor Cyan -"Version=$pythonVer" | Out-File $verFile -Encoding ascii -"Path=$pythonDir" | Out-File $verFile -Encoding ascii -Append -# --- END PATCH --- -Stop-Transcript -Write-Host "Press any key to exit..." -ForegroundColor Cyan -Pause + # Install the service to directly run venv python + app.py + & $nssm install RetroIPTVGuide $venvPython $appPy -exit $LASTEXITCODE \ No newline at end of file + # Set service parameters + & $nssm set RetroIPTVGuide Start SERVICE_AUTO_START + & $nssm set RetroIPTVGuide AppDirectory $repoDir + + Write-Host "NSSM service 'RetroIPTVGuide' installed successfully." -ForegroundColor Green + + # Start the service right away + Start-Service RetroIPTVGuide + Write-Host "Service 'RetroIPTVGuide' started." -ForegroundColor Green + } else { + Write-Warning "NSSM, venv python, or app.py not found. Could not create service." + } +} catch { + Write-Warning "Failed to configure NSSM service: $_" +} + +echo "" +Write-Host "Installation complete!" -ForegroundColor Cyan +echo "End time: $(date)" +echo "Access the server in your browser at: http://:5000" +echo "Default login: admin / strongpassword123" +echo "NOTE: This is a **BETA build**. Do not expose it directly to the public internet." +echo "" + +# === Done === +Stop-Transcript +pause diff --git a/uninstall_windows.ps1 b/uninstall_windows.ps1 index 1b6ea45..4514deb 100644 --- a/uninstall_windows.ps1 +++ b/uninstall_windows.ps1 @@ -1,322 +1,189 @@ -<# uninstall_windows.ps1 - Complete uninstaller for RetroIPTVGuide - - Stops and removes Windows Service - - Removes RetroIPTVGuide repo + venv - - Removes Git Bash (if installed) - - Removes Python (if installed) - - Removes logs after transcript -#> +# RetroIPTVGuide Windows Uninstaller +# ================================== -$LogDir = Join-Path $PSScriptRoot "logs" -if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Force -Path $LogDir | Out-Null } -$TimeStamp = Get-Date -Format "yyyyMMdd_HHmmss" -$LogFile = Join-Path $LogDir "uninstall_$TimeStamp.log" + + +# Setup logging +$LogDir = "$PSScriptRoot\logs" +if (!(Test-Path $LogDir)) { New-Item -ItemType Directory -Force -Path $LogDir | Out-Null } +$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss" +$LogFile = "$LogDir\uninstall_$Timestamp.log" Start-Transcript -Path $LogFile -Force +Write-Host "=== RetroIPTVGuide Windows Uninstaller ===" -ForegroundColor Cyan +Write-Host "Timestamp: $(Get-Date)" -ForegroundColor Cyan +Write-Host "Log file: $LogFile" -ForegroundColor Cyan # Elevation check $IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $IsAdmin) { Write-Host "Re-launching with Administrator privileges..." -ForegroundColor Yellow -# --- PATCH: Corrected Python uninstall using version + path file --- -$pythonVerFile = Join-Path $PSScriptRoot "logs\python_version.txt" -if (Test-Path $pythonVerFile) { - $lines = Get-Content $pythonVerFile - $pythonVersion = ($lines | Where-Object { $_ -like "Version=*" }) -replace "Version=", "" - $pythonPath = ($lines | Where-Object { $_ -like "Path=*" }) -replace "Path=", "" - - Write-Host "Attempting to uninstall Python $pythonVersion from $pythonPath..." -ForegroundColor Yellow + Stop-Transcript + Start-Process -FilePath "powershell.exe" -Verb RunAs -ArgumentList "-ExecutionPolicy Bypass -File `"$PSCommandPath`"" + exit +} - $uninstaller = Join-Path $pythonPath "uninstall.exe" - if (Test-Path $uninstaller) { - & $uninstaller /quiet | Out-Null - Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green +# Stop and remove RetroIPTVGuide service via NSSM +$serviceName = "RetroIPTVGuide" +try { + if (Get-Service -Name $serviceName -ErrorAction SilentlyContinue) { + Write-Host "Stopping service $serviceName..." -ForegroundColor Yellow + Stop-Service $serviceName -Force -ErrorAction SilentlyContinue + Write-Host "Removing service $serviceName..." -ForegroundColor Yellow + & nssm remove $serviceName confirm } else { - Write-Warning "Uninstaller not found at $uninstaller. Trying registry lookup..." - $uninstallKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" - $pythonKey = Get-ChildItem $uninstallKey | Where-Object { - $_.GetValue("DisplayName") -like "Python $pythonVersion*" - } | Select-Object -First 1 - if ($pythonKey) { - $uninstallString = $pythonKey.GetValue("UninstallString", $null) - if ($uninstallString) { - Write-Host "Running registry uninstall for Python $pythonVersion..." -ForegroundColor Yellow - & cmd.exe /c $uninstallString /quiet | Out-Null - Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green - } else { - Write-Warning "Registry entry found but no uninstall string for Python $pythonVersion." - } - } else { - Write-Warning "No registry entry found for Python $pythonVersion." - } + Write-Host "Service $serviceName not found." -ForegroundColor DarkYellow } -} else { - Write-Host "No python_version.txt found, falling back to existing uninstall logic..." -ForegroundColor Yellow +} catch { + Write-Warning "Error while removing $serviceName service: $_" } -# --- END PATCH --- -# --- PATCH: Corrected Python uninstall with cleanup --- -$pythonVerFile = Join-Path $PSScriptRoot "logs\python_version.txt" -if (Test-Path $pythonVerFile) { - $lines = Get-Content $pythonVerFile - $pythonVersion = ($lines | Where-Object { $_ -like "Version=*" }) -replace "Version=", "" - $pythonPath = ($lines | Where-Object { $_ -like "Path=*" }) -replace "Path=", "" - Write-Host "Attempting to uninstall Python $pythonVersion from $pythonPath..." -ForegroundColor Yellow +# Remove firewall rule +try { + Write-Host "Removing Windows Firewall port rule for RetroIPTVGuide..." -ForegroundColor Yellow + netsh advfirewall firewall delete rule name="RetroIPTVGuide" +} catch { + Write-Warning "Could not remove firewall rule: $_" +} - $uninstaller = Join-Path $pythonPath "uninstall.exe" - if (Test-Path $uninstaller) { - & $uninstaller /quiet | Out-Null - Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green - } else { - Write-Warning "Uninstaller not found at $uninstaller. Trying registry lookup..." - $uninstallKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" - $pythonKey = Get-ChildItem $uninstallKey | Where-Object { - $_.GetValue("DisplayName") -like "Python $pythonVersion*" - } | Select-Object -First 1 - if ($pythonKey) { - $uninstallString = $pythonKey.GetValue("UninstallString", $null) - if ($uninstallString) { - Write-Host "Running registry uninstall for Python $pythonVersion..." -ForegroundColor Yellow - & cmd.exe /c $uninstallString /quiet | Out-Null - Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green - if (Test-Path $pythonPath) { - try { - Remove-Item -Recurse -Force $pythonPath - Write-Host "Removed leftover Python directory: $pythonPath" -ForegroundColor Green - } catch { - Write-Warning "Could not remove Python directory $pythonPath: $_" - } - } - } else { - Write-Warning "Registry entry found but no uninstall string for Python $pythonVersion." +# Remove RetroIPTVGuide installation folder +#$installDir = "$PSScriptRoot" +#if (Test-Path $installDir) { +# Write-Host "Removing install directory $installDir..." -ForegroundColor Yellow +# try { +# Remove-Item -Recurse -Force $installDir +# Write-Host "Install directory removed." -ForegroundColor Green +# } catch { +# Write-Warning "Could not remove ${installDir}: $_" +# } +#} else { +# Write-Host "Install directory not found: $installDir" -ForegroundColor DarkYellow +#} + +## Optional cleanup of dependencies installed by Chocolatey +#function Uninstall-ChocoPackage($pkgName) { +# if (Get-Command choco.exe -ErrorAction SilentlyContinue) { +# $installed = choco list | Select-String -Pattern "^$pkgName" +# if ($installed) { +# Write-Host "Uninstalling $pkgName via Chocolatey..." -ForegroundColor Yellow +# choco uninstall $pkgName -y | Out-Null +# } else { +# Write-Host "$pkgName not found in Chocolatey, skipping." -ForegroundColor DarkYellow +# } +# } else { +# Write-Host "Chocolatey not found, cannot uninstall $pkgName." -ForegroundColor DarkYellow +# } +#} +# +#Uninstall-ChocoPackage "python" +#Uninstall-ChocoPackage "python3" +#Uninstall-ChocoPackage "nssm" +#Uninstall-ChocoPackage "git" +#Uninstall-ChocoPackage "git.install" + +# Improved Chocolatey uninstall function +function Uninstall-ChocoPackagePrefix($pkgPrefix) { + if (Get-Command choco.exe -ErrorAction SilentlyContinue) { + $installed = choco list | ForEach-Object { ($_ -split ' ')[0] } | Where-Object { $_ -like "$pkgPrefix*" } + if ($installed) { + foreach ($pkg in $installed) { + Write-Host "Uninstalling $pkg via Chocolatey..." -ForegroundColor Yellow + choco uninstall $pkg -y | Out-Null } } else { - Write-Warning "No registry entry found for Python $pythonVersion." + Write-Host "No packages found with prefix '$pkgPrefix', skipping." -ForegroundColor DarkYellow } + } else { + Write-Host "Chocolatey not found, cannot uninstall packages with prefix '$pkgPrefix'." -ForegroundColor DarkYellow } -} else { - Write-Host "No python_version.txt found, falling back to existing uninstall logic..." -ForegroundColor Yellow -} -# --- END PATCH --- - Stop-Transcript - Start-Process -FilePath "powershell.exe" -Verb RunAs -ArgumentList "-ExecutionPolicy Bypass -File `"$PSCommandPath`"" - exit } -Write-Host "=== RetroIPTVGuide Complete Uninstaller ===" -ForegroundColor Cyan -Write-Host "Timestamp: $(Get-Date)" -Write-Host "Log file: $LogFile" +# Remove all Python variants + NSSM + Git +Uninstall-ChocoPackagePrefix "python" +Uninstall-ChocoPackagePrefix "nssm" +Uninstall-ChocoPackagePrefix "git" -# Stop and remove service -$service = Get-Service -Name "RetroIPTVGuide" -ErrorAction SilentlyContinue -if ($service) { - try { - if ($service.Status -eq "Running") { - Stop-Service -Name "RetroIPTVGuide" -Force - } - $nssmPath = "C:\nssm\nssm.exe" - if (Test-Path $nssmPath) { - & $nssmPath remove RetroIPTVGuide confirm - Write-Host "RetroIPTVGuide service removed." -ForegroundColor Green - } else { - sc.exe delete RetroIPTVGuide | Out-Null - Write-Host "RetroIPTVGuide service removed via sc.exe." -ForegroundColor Green - } - } catch { - Write-Warning "Could not remove RetroIPTVGuide service automatically." + +# --- Remove registry App Paths aliases for python/python3 --- +try { + if (Test-Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\python.exe") { + Remove-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\python.exe" -Recurse -Force + Write-Host "Removed App Path alias: python.exe" -ForegroundColor Yellow } -} else { - Write-Host "RetroIPTVGuide service not found." -ForegroundColor Yellow + if (Test-Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\python3.exe") { + Remove-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\python3.exe" -Recurse -Force + Write-Host "Removed App Path alias: python3.exe" -ForegroundColor Yellow + } +} catch { + Write-Warning "Failed to remove python/python3 App Path aliases: $_" } -# Candidate paths -$CandidateDirs = @( - (Join-Path $PSScriptRoot "RetroIPTVGuide"), - (Join-Path $env:USERPROFILE "RetroIPTVGuide"), - (Join-Path ($env:HOMEDRIVE + $env:HOMEPATH) "RetroIPTVGuide"), - (Join-Path $env:USERPROFILE "Desktop\RetroIPTVGuide"), - "C:\RetroIPTVGuide" +# --- Optionally restore Microsoft Store stubs (App Execution Aliases) --- +$windowsApps = "$env:LOCALAPPDATA\Microsoft\WindowsApps" +$stubTargets = @( + "python.exe", + "python3.exe" ) -foreach ($dir in $CandidateDirs) { - if (Test-Path $dir) { +foreach ($stub in $stubTargets) { + $stubPath = Join-Path $windowsApps $stub + if (-not (Test-Path $stubPath)) { try { - Remove-Item -Recurse -Force $dir - Write-Host "Removed RetroIPTVGuide folder: $dir" -ForegroundColor Green - break + # Recreate as a zero-byte placeholder to mimic default behavior + New-Item -Path $stubPath -ItemType File -Force | Out-Null + Write-Host "Restored Microsoft Store alias stub: $stubPath" -ForegroundColor Yellow } catch { - Write-Error "Failed to remove $dir" + Write-Warning "Failed to restore Store alias ${stub}: $_" } } } -# Remove venv -$venvDirs = @( - (Join-Path $PSScriptRoot "venv"), - (Join-Path $env:USERPROFILE "venv"), - (Join-Path ($env:HOMEDRIVE + $env:HOMEPATH) "venv") -) -foreach ($vdir in $venvDirs) { - if (Test-Path $vdir) { - try { - Remove-Item -Recurse -Force $vdir - Write-Host "Removed venv: $vdir" -ForegroundColor Green - } catch { - Write-Error "Failed to remove venv: $vdir" - } - } -} +Write-Host "" +Write-Host "Would you like to completely uninstall ALL remaining Chocolatey packages and Chocolatey itself?" -ForegroundColor Yellow +$fullUninstall = Read-Host "Type yes or no" +Write-Output "User response to full uninstall prompt: $fullUninstall" -# Attempt to remove Git Bash -$gitUninstall = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall" -ErrorAction SilentlyContinue | - Get-ItemProperty | Where-Object { $_.DisplayName -like "Git*" } -if ($gitUninstall -and $gitUninstall.UninstallString) { +if ($fullUninstall.ToLower() -eq "yes") { try { - Start-Process -FilePath "cmd.exe" -ArgumentList "/c",$gitUninstall.UninstallString,"/VERYSILENT","/NORESTART" -Wait - Write-Host "Git Bash uninstalled." -ForegroundColor Green - } catch { - Write-Warning "Could not uninstall Git Bash automatically." - } -} else { - Write-Host "Git Bash not found." -ForegroundColor Yellow -} - -# Attempt to remove Python -$pyUninstall = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall" -ErrorAction SilentlyContinue | - Get-ItemProperty | Where-Object { $_.DisplayName -like "Python*" } -if ($pyUninstall -and $pyUninstall.UninstallString) { - try { - Start-Process -FilePath "cmd.exe" -ArgumentList "/c",$pyUninstall.UninstallString,"/quiet" -Wait - Write-Host "Python uninstalled." -ForegroundColor Green - } catch { - Write-Warning "Could not uninstall Python automatically." - } -} else { - Write-Host "Python not found." -ForegroundColor Yellow -} - -# --- PATCH: Stop and remove RetroIPTVGuide service, firewall rule, and NSSM --- -if (Get-Service RetroIPTVGuide -ErrorAction SilentlyContinue) { - Write-Host "Stopping RetroIPTVGuide service..." -ForegroundColor Yellow - Stop-Service RetroIPTVGuide -Force -ErrorAction SilentlyContinue -} - -$nssmPath = "C:\nssm\nssm.exe" -if (Test-Path $nssmPath) { - Write-Host "Removing RetroIPTVGuide service..." -ForegroundColor Yellow - & $nssmPath remove RetroIPTVGuide confirm -} - -Write-Host "Removing Windows Firewall port rule for RetroIPTVGuide..." -ForegroundColor Yellow -netsh advfirewall firewall delete rule name="RetroIPTVGuide" | Out-Null - -if (Test-Path "C:\nssm") { - Write-Host "Removing NSSM installation..." -ForegroundColor Yellow - Remove-Item -Recurse -Force "C:\nssm" -} - -# --- PATCH: Stop and remove RetroIPTVGuide service, firewall rule, and NSSM --- -if (Get-Service RetroIPTVGuide -ErrorAction SilentlyContinue) { - Write-Host "Stopping RetroIPTVGuide service..." -ForegroundColor Yellow - Stop-Service RetroIPTVGuide -Force -ErrorAction SilentlyContinue -} - -# Try NSSM first -$nssmPath = "C:\nssm\nssm.exe" -if (Test-Path $nssmPath) { - Write-Host "Removing RetroIPTVGuide service via NSSM..." -ForegroundColor Yellow - & $nssmPath remove RetroIPTVGuide confirm -} - -# Always try SC as a fallback to ensure service deletion -Write-Host "Ensuring RetroIPTVGuide service is deleted..." -ForegroundColor Yellow -sc.exe delete RetroIPTVGuide | Out-Null - -Write-Host "Removing Windows Firewall port rule for RetroIPTVGuide..." -ForegroundColor Yellow -netsh advfirewall firewall delete rule name="RetroIPTVGuide" | Out-Null - -if (Test-Path "C:\nssm") { - Write-Host "Removing NSSM installation..." -ForegroundColor Yellow - Remove-Item -Recurse -Force "C:\nssm" -} -# --- END PATCH --- - -# --- END PATCH --- -# --- PATCH: Python uninstall using version + path file --- -$pythonVerFile = Join-Path $PSScriptRoot "logs\python_version.txt" -if (Test-Path $pythonVerFile) { - $lines = Get-Content $pythonVerFile - $pythonVersion = ($lines | Where-Object { $_ -like "Version=*" }) -replace "Version=", "" - $pythonPath = ($lines | Where-Object { $_ -like "Path=*" }) -replace "Path=", "" - - Write-Host "Attempting to uninstall Python $pythonVersion from $pythonPath..." -ForegroundColor Yellow - - $uninstaller = Join-Path $pythonPath "uninstall.exe" - if (-not (Test-Path $uninstaller)) { - # fallback: use Modify/Repair entry in registry if uninstall.exe missing - $uninstallKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" - $pythonKey = Get-ChildItem $uninstallKey | Where-Object { - $_.GetValue("DisplayName") -like "Python $pythonVersion*" - } - if ($pythonKey) { - $uninstallString = $pythonKey.GetValue("UninstallString", $null) - if ($uninstallString) { - Write-Host "Running registry uninstall for Python $pythonVersion..." -ForegroundColor Yellow - & cmd.exe /c $uninstallString /quiet | Out-Null - } - } - } - -} else { - Write-Host "No python_version.txt found, falling back to existing uninstall logic..." -ForegroundColor Yellow -} -# --- END PATCH --- -# --- PATCH: Corrected Python uninstall using version + path file --- -$pythonVerFile = Join-Path $PSScriptRoot "logs\python_version.txt" -if (Test-Path $pythonVerFile) { - $lines = Get-Content $pythonVerFile - $pythonVersion = ($lines | Where-Object { $_ -like "Version=*" }) -replace "Version=", "" - $pythonPath = ($lines | Where-Object { $_ -like "Path=*" }) -replace "Path=", "" + Write-Host "" + Write-Host "Proceeding with full removal of all Chocolatey packages..." -ForegroundColor Red + + # Capture installed packages + $rawInstalled = & choco list 2>$null + if ($rawInstalled -is [string]) { $rawInstalled = $rawInstalled -split "`r?`n" } + + $installed = $rawInstalled | Where-Object { + ($_ -notmatch "^Chocolatey v") -and + ($_ -notmatch "Did you know Pro") -and + ($_ -notmatch "Features\? Learn more") -and + ($_ -notmatch "Package Synchronizer") -and + ($_ -notmatch "packages installed") -and + ($_ -ne "") + } - Write-Host "Attempting to uninstall Python $pythonVersion from $pythonPath..." -ForegroundColor Yellow + # Extract package names (first token of each line) + $pkgNames = $installed | ForEach-Object { ($_ -split " ")[0] } - $uninstaller = Join-Path $pythonPath "uninstall.exe" - if (Test-Path $uninstaller) { - & $uninstaller /quiet | Out-Null - Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green - } else { - Write-Warning "Uninstaller not found at $uninstaller. Trying registry lookup..." - $uninstallKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" - $pythonKey = Get-ChildItem $uninstallKey | Where-Object { - $_.GetValue("DisplayName") -like "Python $pythonVersion*" - } | Select-Object -First 1 - if ($pythonKey) { - $uninstallString = $pythonKey.GetValue("UninstallString", $null) - if ($uninstallString) { - Write-Host "Running registry uninstall for Python $pythonVersion..." -ForegroundColor Yellow - & cmd.exe /c $uninstallString /quiet | Out-Null - Write-Host "Python $pythonVersion uninstalled successfully." -ForegroundColor Green - } else { - Write-Warning "Registry entry found but no uninstall string for Python $pythonVersion." + if ($pkgNames) { + foreach ($pkg in $pkgNames) { + Write-Host "Uninstalling $pkg ..." -ForegroundColor Cyan + choco uninstall -y $pkg | Out-Null } - } else { - Write-Warning "No registry entry found for Python $pythonVersion." } + + # Finally uninstall Chocolatey itself + Write-Host "Uninstalling Chocolatey..." -ForegroundColor Cyan + choco uninstall -y chocolatey | Out-Null + + Write-Host "Full Chocolatey removal complete." -ForegroundColor Green + Write-Output "Full Chocolatey removal complete." + } catch { + Write-Warning "Failed to completely remove all Chocolatey packages: $_" } } else { - Write-Host "No python_version.txt found, falling back to existing uninstall logic..." -ForegroundColor Yellow + Write-Host "Leaving remaining Chocolatey packages and Chocolatey itself installed." -ForegroundColor Cyan } -# --- END PATCH --- -Stop-Transcript -Write-Host "Press any key to exit..." -ForegroundColor Cyan -Pause -# Clean logs after transcript ends -#if (Test-Path $LogDir) { -# try { -# Remove-Item -Recurse -Force $LogDir -# Write-Host "Removed logs folder: $LogDir" -ForegroundColor Green -# } catch { -# Write-Warning "Failed to remove logs folder: $LogDir" -# } -#} +Stop-Transcript +Write-Host "=== Uninstallation complete ===" -ForegroundColor Cyan +pause From 8b8e9e349fb6a04560eb6dac83645e584e729be7 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Fri, 3 Oct 2025 21:57:36 -0500 Subject: [PATCH 4/5] Update for 3.0.0 --- bump_version.py | 55 ++++++++++++++++++++++++++++++++++++++++++------- install.sh | 39 +++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 8 deletions(-) diff --git a/bump_version.py b/bump_version.py index 29a28be..cd36837 100644 --- a/bump_version.py +++ b/bump_version.py @@ -15,9 +15,12 @@ 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") def update_app_py(new_version: str): - """Update APP_VERSION in app.py""" + """Update APP_VERSION in app.py, add if missing""" content = APP_FILE.read_text().splitlines() updated = [] found = False @@ -28,8 +31,8 @@ def update_app_py(new_version: str): else: updated.append(line) if not found: - print("⚠️ APP_VERSION not found in app.py") - sys.exit(1) + updated.insert(0, f'APP_VERSION = "v{new_version}"') + print("ℹ️ APP_VERSION not found in app.py, added at top") APP_FILE.write_text("\n".join(updated) + "\n") print(f"✅ Updated app.py to v{new_version}") @@ -54,9 +57,7 @@ def update_changelog(new_version: str): inserted = False for i, line in enumerate(changelog): updated.append(line) - # Find the first --- *after* the Unreleased section if line.strip() == "---" and not inserted: - # Look back: did we already pass Unreleased? if any("## [Unreleased]" in l for l in changelog[:i]): updated.append("") # spacing updated.extend(new_block) @@ -69,11 +70,45 @@ def update_changelog(new_version: str): CHANGELOG_FILE.write_text("\n".join(updated) + "\n") print(f"✅ Inserted v{new_version} section into CHANGELOG.md") +def update_script_version(file: Path, new_version: str, is_bash: bool): + """Update or insert version string in shell or PowerShell scripts""" + if not file.exists(): + print(f"⚠️ {file} not found, skipping") + return + + content = file.read_text().splitlines() + updated = [] + found = False + + # Regex for version line + if is_bash: + pattern = re.compile(r'^\s*VERSION\s*=\s*".*"') + replacement = f'VERSION="{new_version}"' + else: # PowerShell + pattern = re.compile(r'^\s*\$?VERSION\s*=\s*".*"') + replacement = f'$VERSION = "{new_version}"' + + for line in content: + if pattern.match(line): + updated.append(replacement) + found = True + else: + updated.append(line) + + if not found: + # Insert at top + updated.insert(0, replacement) + print(f"ℹ️ VERSION not found in {file}, added at top") + + file.write_text("\n".join(updated) + "\n") + print(f"✅ Updated {file} to v{new_version}") + def git_commit(new_version: str): """Commit changes with git""" try: subprocess.run( - ["git", "add", str(APP_FILE), str(CHANGELOG_FILE)], + ["git", "add", str(APP_FILE), str(CHANGELOG_FILE), + str(INSTALL_WIN), str(UNINSTALL_WIN), str(UNINSTALL_SH)], check=True ) subprocess.run( @@ -89,15 +124,19 @@ def main(): print("Usage: python bump_version.py [--commit]") sys.exit(1) - new_version = sys.argv[1].lstrip("v") # allow 'v2.4.0' or '2.4.0' + new_version = sys.argv[1].lstrip("v") do_commit = "--commit" in sys.argv update_app_py(new_version) update_changelog(new_version) + # Update other scripts + 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) + if do_commit: git_commit(new_version) if __name__ == "__main__": main() - diff --git a/install.sh b/install.sh index 8aeecbf..867f222 100644 --- a/install.sh +++ b/install.sh @@ -93,6 +93,37 @@ if [[ "$ENVIRONMENT" == "LINUX" || "$ENVIRONMENT" == "WSL" ]]; then fi fi +echo "" +echo "============================================================" +echo " RetroIPTVGuide Installer Agreement " +echo "============================================================" +echo "" +echo "This installer will perform the following actions:" +echo " - Detect whether you are running on Linux or WSL" +echo " - Ensure the script is run with sudo" +echo " - Create dedicated system user 'iptv' (if not already present)" +echo " - Ensure python3-venv package is installed" +echo " - Copy project files into /home/iptv/iptv-server" +echo " - Create and configure a Python virtual environment" +echo " - Upgrade pip and install requirements" +echo " - Create and enable the iptv-server systemd service" +echo " - Start the iptv-server service" +echo "" +echo "By continuing, you acknowledge and 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; the author provides NO WARRANTY." +echo " - The author is NOT responsible for any damage, data loss," +echo " or security vulnerabilities created by this installation." +echo "" +read -p "Do you agree to these terms? (yes/no): " agreement + +if [ "$agreement" != "yes" ]; then + echo "Installation aborted by user." + exit 1 +fi + + # Variables APP_USER="iptv" APP_HOME="/home/$APP_USER" @@ -184,6 +215,14 @@ else echo "Unsupported environment: $OSTYPE" exit 1 fi + +echo "" +echo "Installation complete!" +echo "End time: $(date)" +echo "Access the server in your browser at: http://:5000" +echo "Default login: admin / strongpassword123" +echo "NOTE: This is a **BETA build**. Do not expose it directly to the public internet." +echo "" } if [ "$ENVIRONMENT" = "GITBASH" ]; then From edcbf540e030027bc41173ff4b715e24d0b7fba0 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Fri, 3 Oct 2025 23:40:46 -0500 Subject: [PATCH 5/5] 2.3.2 -> 3.0.0 ### Highlights - Added full Windows installer/uninstaller support: - install_windows.ps1 + install.bat for setup - uninstall_windows.ps1 + uninstall.bat for clean removal - Windows installer bootstraps Chocolatey, installs Python, Git, NSSM, and registers a service - Windows uninstaller removes service, firewall rule, and optionally all Chocolatey packages - Enhanced Linux/Git Bash installer (install.sh): - Smarter environment detection (Linux, WSL, Git Bash) - Unified venv path handling for Linux vs Windows - Safer pip upgrade logic - Improved automation: - bump_version.py now updates all install/uninstall scripts across Linux & Windows - Auto-inserts APP_VERSION/ VERSION if missing - Documentation: - Updated README.md with Windows one-liner installer - Updated INSTALL.md with Windows update instructions - Updated ROADMAP.md to reflect v3.0.0 goals completed - Added CHANGELOG.md entry for v3.0.0 ### Fixes - Cleaned up Windows uninstall to avoid duplicate Chocolatey package listings - Ensured firewall rule removal on uninstall - Consistent logging of user agreement + installer actions --- --- CHANGELOG.md | 28 ++++++++++ INSTALL.md | 119 ++++++++++++++++++++++++++++-------------- README.md | 25 +++++---- ROADMAP.md | 12 ++++- app.py | 2 +- bump_version.py | 1 + install.sh | 39 -------------- install_windows.ps1 | 2 + uninstall.sh | 2 + uninstall_windows.ps1 | 1 + 10 files changed, 139 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e31a247..1e392c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,34 @@ This project follows [Semantic Versioning](https://semver.org/). --- +## [3.0.0] - 2025-10-03 +### Added +- **Windows Support**: + - New `install_windows.ps1` and `install.bat` for automated setup. + - New `uninstall_windows.ps1` and `uninstall.bat` for clean removal. + - NSSM service created to run `venv\Scripts\python.exe app.py` automatically. + - Windows installer bootstraps Chocolatey, installs `python`, `git`, and `nssm`. + - Windows uninstaller removes the service, deletes firewall rule for port 5000, and lists remaining Chocolatey packages (with option to remove all). +- **Cross-platform Installer Enhancements**: + - `install.sh` improved to detect Linux, WSL, or Git Bash environments. + - Added pip upgrade check instead of always forcing upgrade. + - Unified handling of venv paths for Linux (`bin/`) and Windows (`Scripts/`). +- **bump_version.py**: + - Now also updates `install_windows.ps1`, `uninstall_windows.ps1`, and `uninstall.sh`. + - Automatically inserts `APP_VERSION`/`VERSION` if missing. + +### Changed +- **Documentation**: + - Updated `README.md` with Windows one-liner install. + - Updated `INSTALL.md` with new Windows instructions and update steps. +- **Uninstall Scripts**: + - Windows uninstall output cleaned to avoid duplicate Chocolatey lists. + - Linux/WSL uninstall script improved to fully remove `iptv-server` systemd service and venv. + +### Fixed +- Consistent logging of user agreement and installer actions. +- Ensured firewall rule removal on Windows during uninstall. + ## [2.3.2] - 2025-09-26 ### Added - Introduced unified **Themes submenu** (Light, Dark, AOL/CompuServe, TV Guide Magazine) across all admin and user pages. diff --git a/INSTALL.md b/INSTALL.md index f55b522..c0891a3 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,25 +1,27 @@ # Installation Guide ## Requirements -- Python 3.10+ -- Linux (Debian/Ubuntu with systemd) **or** Windows (Git Bash with Python 3.12+) +- Python 3.10+ (Linux) / Python 3.12+ (Windows) +- **Linux (Debian/Ubuntu with systemd)** or **Windows 10/11** - Administrative privileges: - **Linux/WSL:** run install/uninstall with `sudo` - - **Windows (Git Bash):** run from an Administrator shell + - **Windows:** run from an Administrator **PowerShell** session --- ## Installation -Clone the repository and run the installer (choose one, no need to do both below) +Clone the repository and run the installer. Choose the command based on your OS. -### Option 1: One-liner (quick setup) +### Linux / WSL + +#### Option 1: One-liner (quick setup) ```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) +#### Option 2: Multi-line (step-by-step) ```bash git clone https://github.com/thehack904/RetroIPTVGuide.git cd RetroIPTVGuide @@ -27,18 +29,43 @@ sudo chmod +x install.sh sudo ./install.sh ``` -### What the installer does -- Detects environment (Linux, WSL, or Git Bash on Windows) -- Creates a system user `iptv` and sets up systemd service (Linux/WSL only) -- Installs into `/home/iptv/iptv-server` (Linux/WSL) or local project folder (Windows) -- Creates Python virtual environment + installs dependencies -- Logs the full install process to `install_YYYY-MM-DD_HH-MM-SS.log` +**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 +- Logs the install to `install_YYYY-MM-DD_HH-MM-SS.log` + +--- + +### Windows 10/11 + +Run this one-liner from an **Administrator PowerShell** prompt: + +```powershell +Invoke-WebRequest https://github.com/thehack904/RetroIPTVGuide/archive/refs/heads/main.zip -OutFile RetroIPTVGuide.zip ; tar -xf RetroIPTVGuide.zip ; cd RetroIPTVGuide-windows ; .\install.bat +``` + +**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 +- Logs the install to `install_YYYY-MM-DD_HH-MM-SS.log` --- ## Access -Once installed, access the guide in your browser: +Once installed, open your browser: ``` http://:5000 @@ -48,17 +75,17 @@ Default login: **admin / strongpassword123** --- -## Updating +## 🔄 Updating -### Linux/WSL +### Linux / WSL -#### Option 1: One-liner (quick update) +#### 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 ``` or -#### Option 2: Step-by-step +#### Step-by-step ```bash sudo -u iptv bash -H cd /home/iptv/iptv-server @@ -70,47 +97,59 @@ sudo systemctl restart iptv-server.service --- -### Windows (Git Bash) +### Windows 10/11 -Run these from the folder where you cloned the repo: +From an **Administrator PowerShell** prompt, go to your RetroIPTVGuide folder and run: -#### Option 1: One-liner -```bash -git fetch --all && git reset --hard origin/main && ./venv/Scripts/python app.py +```powershell +git fetch --all ; git reset --hard origin/main ; Restart-Service RetroIPTVGuide ``` - or -#### Option 2: Step-by-step -```bash +#### Step-by-step +```powershell git fetch --all git reset --hard origin/main -./venv/Scripts/python app.py +Restart-Service RetroIPTVGuide ``` +This will: +- Fetch the latest code from GitHub +- Reset your repo to the latest `windows` branch +- Restart the RetroIPTVGuide service (installed via NSSM) + --- ## Uninstallation -Run the included `uninstall.sh`: - +### Linux / WSL ```bash sudo chmod +x uninstall.sh sudo ./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 -- **Windows (Git Bash):** - - Stops any running `python app.py` process - - Removes the Python virtual environment - - Leaves the project folder in place - -⚠️ To completely remove the project, **manually delete the project folder** after running `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 + +--- + +### Windows +From an Administrator PowerShell prompt: +```powershell +.\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)** + +⚠️ To completely remove the project, manually delete the project folder after uninstalling. --- diff --git a/README.md b/README.md index 946575c..f409538 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ # RetroIPTVGuide -![Version](https://img.shields.io/badge/version-v2.3.2-blue) +![Version](https://img.shields.io/badge/version-v3.0.0-blue) 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. -⚠️ **Note:** This is an initial 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 (v2.3.2) +## ✨ Features (v3.0.0) - 🔑 **User Authentication** - Login/logout system with hashed passwords. - Admin and regular user accounts. @@ -41,15 +41,16 @@ It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https: - AOL/CompuServe - TV Guide Magazine - Theme persistence stored in browser localStorage, applied instantly across all pages. - - **New About Page under Settings menu (v2.3.1)** — shows version, Python, OS, uptime, paths. + - **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 installer (Linux/Windows) (v2.3.0)**. - - **Uninstaller script (v2.3.0)**. - - **Automated version bump tool (`bump_version.py`) (v2.3.1)**. + - **Cross-platform installers (Linux/Windows)**. + - **Uninstaller scripts (Linux/Windows)**. + - **Automated version bump tool (`bump_version.py`)**. +--- ## 🌐 Browser Compatibility This project is designed to work with **all major browsers**. @@ -63,11 +64,15 @@ It has been tested on: The web interface has been tested on: - **Ubuntu (desktop/server)** - **iOS (mobile/tablet)** -- **MacOS** -- **Windows** +- **Android (Samsung Mobile Phone)** +- **macOS** +- **Windows 10/11** ## 🛠️ Installation Platform -The backend server should be installed on a **Debian/Ubuntu machine** for best compatibility. +- **Debian Based Linux (desktop/server)** +- **Windows 10/11** + +## 📺 Screenshots ## 📺 Guide Page ![Guide Screenshot](docs/screenshots/guide.png) diff --git a/ROADMAP.md b/ROADMAP.md index 2dd0f0a..fc8290f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -45,7 +45,10 @@ These are **not yet implemented**, but provide a development path for future rel ### 6. Cross-platform - [ ] Create installable container. - [ ] Create MacOS install/executable. -- [x] Create Microsoft Windows install/executable (basic support via Git Bash + PowerShell bootstrap) (v2.3.0) +- [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] Windows uninstaller cleans service, firewall rule, and optionally removes Chocolatey (v3.0.0) - [ ] Validate/test installer fully on Windows environments ### 7. New Features @@ -74,7 +77,7 @@ These are **not yet implemented**, but provide a development path for future rel ## 📅 Priority Suggestions - Short term: (none — unified UI headers already completed in v2.0.0). - Medium term: log filtering (still pending). -- Medium term: Validate installer/uninstaller on Windows (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. --- @@ -92,3 +95,8 @@ These are **not yet implemented**, but provide a development path for future rel - [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). + + +## ✅ 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). diff --git a/app.py b/app.py index 4671d57..b0cfbb3 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,4 @@ -APP_VERSION = "v2.3.2" +APP_VERSION = "v3.0.0" APP_RELEASE_DATE = "2025-09-26" from flask import Flask, render_template, request, redirect, url_for, flash diff --git a/bump_version.py b/bump_version.py index cd36837..d62f28b 100644 --- a/bump_version.py +++ b/bump_version.py @@ -140,3 +140,4 @@ def main(): if __name__ == "__main__": main() + diff --git a/install.sh b/install.sh index 867f222..8aeecbf 100644 --- a/install.sh +++ b/install.sh @@ -93,37 +93,6 @@ if [[ "$ENVIRONMENT" == "LINUX" || "$ENVIRONMENT" == "WSL" ]]; then fi fi -echo "" -echo "============================================================" -echo " RetroIPTVGuide Installer Agreement " -echo "============================================================" -echo "" -echo "This installer will perform the following actions:" -echo " - Detect whether you are running on Linux or WSL" -echo " - Ensure the script is run with sudo" -echo " - Create dedicated system user 'iptv' (if not already present)" -echo " - Ensure python3-venv package is installed" -echo " - Copy project files into /home/iptv/iptv-server" -echo " - Create and configure a Python virtual environment" -echo " - Upgrade pip and install requirements" -echo " - Create and enable the iptv-server systemd service" -echo " - Start the iptv-server service" -echo "" -echo "By continuing, you acknowledge and 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; the author provides NO WARRANTY." -echo " - The author is NOT responsible for any damage, data loss," -echo " or security vulnerabilities created by this installation." -echo "" -read -p "Do you agree to these terms? (yes/no): " agreement - -if [ "$agreement" != "yes" ]; then - echo "Installation aborted by user." - exit 1 -fi - - # Variables APP_USER="iptv" APP_HOME="/home/$APP_USER" @@ -215,14 +184,6 @@ else echo "Unsupported environment: $OSTYPE" exit 1 fi - -echo "" -echo "Installation complete!" -echo "End time: $(date)" -echo "Access the server in your browser at: http://:5000" -echo "Default login: admin / strongpassword123" -echo "NOTE: This is a **BETA build**. Do not expose it directly to the public internet." -echo "" } if [ "$ENVIRONMENT" = "GITBASH" ]; then diff --git a/install_windows.ps1 b/install_windows.ps1 index 96bd916..2bf2ccf 100644 --- a/install_windows.ps1 +++ b/install_windows.ps1 @@ -1,8 +1,10 @@ +$VERSION = "3.0.0" <# RetroIPTVGuide Windows Installer Clean version with only prerequisite checks and service setup #> + # === Start Transcript === $logDir = "$PSScriptRoot\logs" if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Force -Path $logDir | Out-Null } diff --git a/uninstall.sh b/uninstall.sh index 9c695c8..dfd6b21 100644 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,7 +1,9 @@ +VERSION="3.0.0" #!/usr/bin/env bash # RetroIPTVGuide uninstall script # Run with sudo on Linux; run from Administrator shell on Windows + set -e SERVICE_NAME="iptv-server" diff --git a/uninstall_windows.ps1 b/uninstall_windows.ps1 index 4514deb..ff49b83 100644 --- a/uninstall_windows.ps1 +++ b/uninstall_windows.ps1 @@ -1,3 +1,4 @@ +$VERSION = "3.0.0" # RetroIPTVGuide Windows Uninstaller # ==================================