mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-09-11 12:46:19 +00:00
434 lines
14 KiB
PowerShell
434 lines
14 KiB
PowerShell
# Color definitions
|
|
$colors = @{
|
|
Red = "`e[31m"
|
|
Green = "`e[32m"
|
|
Yellow = "`e[33m"
|
|
Blue = "`e[34m"
|
|
Plain = "`e[0m"
|
|
}
|
|
|
|
# Basic logging functions
|
|
function Write-Log {
|
|
param (
|
|
[string]$Level,
|
|
[string]$Message
|
|
)
|
|
|
|
$color = switch ($Level) {
|
|
"DEG" { $colors.Yellow }
|
|
"ERR" { $colors.Red }
|
|
"INF" { $colors.Green }
|
|
default { $colors.Plain }
|
|
}
|
|
|
|
Write-Host "$($color)[$Level] $Message$($colors.Plain)"
|
|
}
|
|
|
|
function LOGD { param([string]$Message) Write-Log "DEG" $Message }
|
|
function LOGE { param([string]$Message) Write-Log "ERR" $Message }
|
|
function LOGI { param([string]$Message) Write-Log "INF" $Message }
|
|
|
|
# Check admin privileges
|
|
function Test-Administrator {
|
|
$user = [Security.Principal.WindowsIdentity]::GetCurrent()
|
|
$principal = New-Object Security.Principal.WindowsPrincipal($user)
|
|
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
}
|
|
|
|
if (-not (Test-Administrator)) {
|
|
LOGE "ERROR: You must run this script as Administrator!"
|
|
exit 1
|
|
}
|
|
|
|
# Get Windows version information
|
|
$osInfo = Get-WmiObject Win32_OperatingSystem
|
|
$osVersion = [Version]$osInfo.Version
|
|
|
|
# Check minimum Windows version (Windows 10/Server 2016 or higher)
|
|
$minVersion = [Version]"10.0.0.0"
|
|
if ($osVersion -lt $minVersion) {
|
|
LOGE "This script requires Windows 10/Server 2016 or higher"
|
|
exit 1
|
|
}
|
|
|
|
# Variables
|
|
$scriptPath = $PSScriptRoot
|
|
$configPath = Join-Path $scriptPath "config"
|
|
$logFolder = $env:XUI_LOG_FOLDER
|
|
if (-not $logFolder) {
|
|
$logFolder = "C:\ProgramData\3x-ui\logs"
|
|
}
|
|
|
|
$iplimitLogPath = Join-Path $logFolder "3xipl.log"
|
|
$iplimitBannedLogPath = Join-Path $logFolder "3xipl-banned.log"
|
|
|
|
# Function to confirm actions
|
|
function Confirm-Action {
|
|
param (
|
|
[string]$Prompt,
|
|
[string]$DefaultChoice = "N"
|
|
)
|
|
|
|
if ($DefaultChoice) {
|
|
$prompt = "$Prompt [Default $DefaultChoice]: "
|
|
} else {
|
|
$prompt = "$Prompt [Y/N]: "
|
|
}
|
|
|
|
$choice = Read-Host -Prompt $prompt
|
|
if (-not $choice) { $choice = $DefaultChoice }
|
|
|
|
return $choice -in @('Y','y')
|
|
}
|
|
|
|
# Function to restart the service
|
|
function Restart-XUI {
|
|
Stop-Service x-ui -ErrorAction SilentlyContinue
|
|
Start-Service x-ui -ErrorAction SilentlyContinue
|
|
|
|
Start-Sleep -Seconds 2
|
|
|
|
$service = Get-Service x-ui -ErrorAction SilentlyContinue
|
|
if ($service.Status -eq 'Running') {
|
|
LOGI "x-ui restarted successfully"
|
|
} else {
|
|
LOGE "Failed to restart x-ui"
|
|
}
|
|
}
|
|
|
|
# Main menu function
|
|
function Show-Menu {
|
|
Write-Host @"
|
|
|
|
╔────────────────────────────────────────────────╗
|
|
│ $($colors.Green)3X-UI Panel Management Script$($colors.Plain) │
|
|
│ $($colors.Green)0.$($colors.Plain) Exit Script │
|
|
│────────────────────────────────────────────────│
|
|
│ $($colors.Green)1.$($colors.Plain) Install │
|
|
│ $($colors.Green)2.$($colors.Plain) Update │
|
|
│ $($colors.Green)3.$($colors.Plain) Legacy Version │
|
|
│ $($colors.Green)4.$($colors.Plain) Uninstall │
|
|
│────────────────────────────────────────────────│
|
|
│ $($colors.Green)5.$($colors.Plain) Reset Username & Password │
|
|
│ $($colors.Green)6.$($colors.Plain) Reset Web Base Path │
|
|
│ $($colors.Green)7.$($colors.Plain) Reset Settings │
|
|
│ $($colors.Green)8.$($colors.Plain) Change Port │
|
|
│ $($colors.Green)9.$($colors.Plain) View Current Settings │
|
|
│────────────────────────────────────────────────│
|
|
│ $($colors.Green)10.$($colors.Plain) Start │
|
|
│ $($colors.Green)11.$($colors.Plain) Stop │
|
|
│ $($colors.Green)12.$($colors.Plain) Restart │
|
|
│ $($colors.Green)13.$($colors.Plain) Check Status │
|
|
│ $($colors.Green)14.$($colors.Plain) View Logs │
|
|
│────────────────────────────────────────────────│
|
|
│ $($colors.Green)15.$($colors.Plain) Enable Autostart │
|
|
│ $($colors.Green)16.$($colors.Plain) Disable Autostart │
|
|
╚────────────────────────────────────────────────╝
|
|
"@
|
|
|
|
Show-Status
|
|
|
|
$choice = Read-Host "`nPlease enter your selection [0-16]"
|
|
|
|
switch ($choice) {
|
|
"0" { exit 0 }
|
|
"1" { Install-XUI }
|
|
"2" { Update-XUI }
|
|
"3" { Install-LegacyVersion }
|
|
"4" { Uninstall-XUI }
|
|
"5" { Reset-XUICredentials }
|
|
"6" { Reset-WebBasePath }
|
|
"7" { Reset-Settings }
|
|
"8" { Set-XUIPort }
|
|
"9" { Show-Settings }
|
|
"10" { Start-XUI }
|
|
"11" { Stop-XUI }
|
|
"12" { Restart-XUI }
|
|
"13" { Show-Status }
|
|
"14" { Show-Logs }
|
|
"15" { Enable-XUIAutostart }
|
|
"16" { Disable-XUIAutostart }
|
|
default { LOGE "Please enter the correct number [0-16]" }
|
|
}
|
|
|
|
Show-Menu
|
|
}
|
|
|
|
# Show service status
|
|
function Show-Status {
|
|
$service = Get-Service x-ui -ErrorAction SilentlyContinue
|
|
if ($service) {
|
|
Write-Host "Panel Status: " -NoNewline
|
|
if ($service.Status -eq 'Running') {
|
|
Write-Host "$($colors.Green)Running$($colors.Plain)"
|
|
} else {
|
|
Write-Host "$($colors.Red)Stopped$($colors.Plain)"
|
|
}
|
|
} else {
|
|
Write-Host "Panel Status: $($colors.Red)Not Installed$($colors.Plain)"
|
|
}
|
|
}
|
|
|
|
# Main entry point
|
|
if ($args.Count -gt 0) {
|
|
switch ($args[0]) {
|
|
"start" { Start-XUI }
|
|
"stop" { Stop-XUI }
|
|
"restart" { Restart-XUI }
|
|
"status" { Show-Status }
|
|
"enable" { Enable-XUIAutostart }
|
|
"disable" { Disable-XUIAutostart }
|
|
"log" { Show-Logs -LogType "service" }
|
|
"banlog" { Show-Logs -LogType "ban" }
|
|
"update" { Update-XUI }
|
|
"install" { Install-XUI }
|
|
"uninstall" { Uninstall-XUI }
|
|
"settings" { Show-Settings }
|
|
"legacy" { Install-LegacyVersion }
|
|
default { Show-Usage }
|
|
}
|
|
} else {
|
|
Show-Menu
|
|
}
|
|
|
|
# Add these functions after the existing logging functions
|
|
|
|
function Install-BasePackages {
|
|
# Check if winget is available
|
|
if (Get-Command winget -ErrorAction SilentlyContinue) {
|
|
Write-Host "Installing required packages using winget..."
|
|
winget install -e --id Git.Git
|
|
winget install -e --id Microsoft.PowerShell
|
|
winget install -e --id Nssm.Nssm # Add NSSM installation
|
|
} else {
|
|
Write-Host -ForegroundColor $colors.Red "Please install winget package manager or install Git and NSSM manually"
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
function Install-XUI {
|
|
param([string]$version = "")
|
|
|
|
$installDir = "C:\Program Files\x-ui"
|
|
|
|
# Create install directory if it doesn't exist
|
|
if (-not (Test-Path $installDir)) {
|
|
New-Item -ItemType Directory -Path $installDir -Force
|
|
}
|
|
|
|
# Get latest version if not specified
|
|
if (-not $version) {
|
|
$version = (Invoke-RestMethod "https://api.github.com/repos/MHSanaei/3x-ui/releases/latest").tag_name
|
|
}
|
|
|
|
$arch = Get-CPUArchitecture
|
|
$downloadUrl = "https://github.com/MHSanaei/3x-ui/releases/download/${version}/x-ui-windows-${arch}.zip"
|
|
$zipFile = Join-Path $installDir "x-ui.zip"
|
|
|
|
# Download and extract
|
|
Invoke-WebRequest -Uri $downloadUrl -OutFile $zipFile
|
|
Expand-Archive -Path $zipFile -DestinationPath $installDir -Force
|
|
Remove-Item $zipFile
|
|
|
|
# Create service script
|
|
$servicePath = Join-Path $installDir "x-ui-service.ps1"
|
|
@"
|
|
# Service script content
|
|
`$process = Start-Process -FilePath "C:\Program Files\x-ui\x-ui.exe" -NoNewWindow -PassThru
|
|
while (-not `$process.HasExited) {
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
"@ | Set-Content $servicePath
|
|
|
|
# Register service using nssm
|
|
if (Get-Command nssm -ErrorAction SilentlyContinue) {
|
|
nssm install x-ui powershell
|
|
nssm set x-ui Application "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
|
|
nssm set x-ui AppParameters "-ExecutionPolicy Bypass -NoProfile -File `"$servicePath`""
|
|
nssm start x-ui
|
|
} else {
|
|
Write-Host -ForegroundColor $colors.Red "NSSM is not installed. Please install it to run x-ui as a service."
|
|
}
|
|
|
|
Configure-AfterInstall
|
|
Write-Host -ForegroundColor $colors.Green "x-ui ${version} installation finished"
|
|
}
|
|
|
|
function Update-XUI {
|
|
if (-not (Confirm-Action "This will reinstall the latest version. Continue?" "Y")) {
|
|
LOGE "Cancelled"
|
|
return
|
|
}
|
|
|
|
Stop-Service x-ui
|
|
Install-XUI
|
|
Start-Service x-ui
|
|
LOGI "Update complete, service restarted"
|
|
}
|
|
|
|
function Uninstall-XUI {
|
|
if (-not (Confirm-Action "Are you sure you want to uninstall x-ui?" "N")) {
|
|
return
|
|
}
|
|
|
|
Stop-Service x-ui
|
|
nssm remove x-ui confirm
|
|
Remove-Item "C:\Program Files\x-ui" -Recurse -Force
|
|
LOGI "x-ui uninstalled successfully"
|
|
}
|
|
|
|
function Reset-XUICredentials {
|
|
if (-not (Confirm-Action "Reset username and password?" "N")) {
|
|
return
|
|
}
|
|
|
|
$config = Get-Content "C:\Program Files\x-ui\config.json" | ConvertFrom-Json
|
|
|
|
$newUsername = Read-Host "Enter new username (leave blank for random)"
|
|
if (-not $newUsername) {
|
|
$newUsername = -join ((65..90) + (97..122) | Get-Random -Count 8 | ForEach-Object {[char]$_})
|
|
}
|
|
|
|
$newPassword = Read-Host "Enter new password (leave blank for random)"
|
|
if (-not $newPassword) {
|
|
$newPassword = -join ((65..90) + (97..122) + (48..57) | Get-Random -Count 12 | ForEach-Object {[char]$_})
|
|
}
|
|
|
|
$config.username = $newUsername
|
|
$config.password = $newPassword
|
|
|
|
$config | ConvertTo-Json | Set-Content "C:\Program Files\x-ui\config.json"
|
|
|
|
LOGI "Credentials updated successfully"
|
|
Write-Host "New username: $newUsername"
|
|
Write-Host "New password: $newPassword"
|
|
|
|
Restart-XUI
|
|
}
|
|
|
|
function Show-Usage {
|
|
Write-Host @"
|
|
Usage: x-ui [command]
|
|
Commands:
|
|
start - Start x-ui panel
|
|
stop - Stop x-ui panel
|
|
restart - Restart x-ui panel
|
|
status - Check x-ui status
|
|
enable - Enable x-ui on system startup
|
|
disable - Disable x-ui on system startup
|
|
log - Show x-ui logs
|
|
banlog - Show ban logs
|
|
update - Update x-ui panel
|
|
install - Install x-ui panel
|
|
uninstall - Uninstall x-ui panel
|
|
settings - Show current settings
|
|
legacy - Install specific version
|
|
"@
|
|
}
|
|
|
|
function Get-CPUArchitecture {
|
|
$arch = [System.Environment]::GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
|
|
if ($arch -eq "AMD64") { return "amd64" }
|
|
elseif ($arch -eq "X86") { return "386" }
|
|
elseif ($arch -eq "ARM64") { return "arm64" }
|
|
else { return "amd64" } # Default to amd64
|
|
}
|
|
|
|
function Start-XUI {
|
|
$service = Get-Service x-ui -ErrorAction SilentlyContinue
|
|
if ($service.Status -eq 'Running') {
|
|
LOGI "Panel is already running"
|
|
return
|
|
}
|
|
Start-Service x-ui
|
|
Start-Sleep -Seconds 2
|
|
if ((Get-Service x-ui).Status -eq 'Running') {
|
|
LOGI "x-ui Started Successfully"
|
|
} else {
|
|
LOGE "Failed to start x-ui"
|
|
}
|
|
}
|
|
|
|
function Stop-XUI {
|
|
Stop-Service x-ui -ErrorAction SilentlyContinue
|
|
if ((Get-Service x-ui).Status -eq 'Stopped') {
|
|
LOGI "x-ui Stopped Successfully"
|
|
} else {
|
|
LOGE "Failed to stop x-ui"
|
|
}
|
|
}
|
|
|
|
function Enable-XUIAutostart {
|
|
Set-Service x-ui -StartupType Automatic
|
|
LOGI "x-ui has been enabled to start on system boot"
|
|
}
|
|
|
|
function Disable-XUIAutostart {
|
|
Set-Service x-ui -StartupType Manual
|
|
LOGI "x-ui has been disabled from starting on system boot"
|
|
}
|
|
|
|
function Show-Logs {
|
|
param (
|
|
[string]$LogType = "service"
|
|
)
|
|
|
|
switch ($LogType) {
|
|
"service" {
|
|
$logPath = Join-Path $logFolder "x-ui.log"
|
|
if (Test-Path $logPath) {
|
|
Get-Content $logPath -Tail 50
|
|
} else {
|
|
LOGE "Log file not found"
|
|
}
|
|
}
|
|
"ban" {
|
|
if (Test-Path $iplimitBannedLogPath) {
|
|
Get-Content $iplimitBannedLogPath -Tail 50
|
|
} else {
|
|
LOGE "Ban log file not found"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Show-Settings {
|
|
$configFile = Join-Path $installDir "config.json"
|
|
if (Test-Path $configFile) {
|
|
$config = Get-Content $configFile | ConvertFrom-Json
|
|
$serverIP = (Invoke-WebRequest -Uri "https://api.ipify.org" -UseBasicParsing).Content
|
|
|
|
Write-Host "Current Settings:"
|
|
Write-Host "----------------------------------------"
|
|
Write-Host "Username: $($config.username)"
|
|
Write-Host "Port: $($config.port)"
|
|
Write-Host "Base Path: $($config.webBasePath)"
|
|
Write-Host "Panel URL: http://${serverIP}:$($config.port)$($config.webBasePath)"
|
|
Write-Host "----------------------------------------"
|
|
} else {
|
|
LOGE "Configuration file not found"
|
|
}
|
|
}
|
|
|
|
function Set-XUIPort {
|
|
$port = Read-Host "Enter new port number [1-65535]"
|
|
if ($port -match '^\d+$' -and [int]$port -ge 1 -and [int]$port -le 65535) {
|
|
$configFile = Join-Path $installDir "config.json"
|
|
$config = Get-Content $configFile | ConvertFrom-Json
|
|
$config.port = [int]$port
|
|
$config | ConvertTo-Json | Set-Content $configFile
|
|
LOGI "Port updated successfully. Restarting service..."
|
|
Restart-XUI
|
|
} else {
|
|
LOGE "Invalid port number"
|
|
}
|
|
}
|
|
|
|
function Install-LegacyVersion {
|
|
$version = Read-Host "Enter the panel version (like 2.4.0)"
|
|
if (-not $version) {
|
|
LOGE "Version cannot be empty"
|
|
return
|
|
}
|
|
Install-XUI -version "v$version"
|
|
}
|