Public/Start-BATCRelayBot.ps1
|
function Start-BATCRelayBot { <# .SYNOPSIS Starts the BATC Relay Bot in the background. .DESCRIPTION Reads config.json, starts VoiceMeeter and BeyondATC if not running, waits for them to initialize, then starts bot.py in the background. Logs output to logs\bot_output.log and logs\bot_error.log. .PARAMETER BotPath Path to the bot installation directory. Defaults to $env:USERPROFILE\AppData\Local\BATCRelayBot .EXAMPLE Start-BATCRelayBot .EXAMPLE Start-BATCRelayBot -BotPath "D:\MyBot\BATCRelayBot" #> param( [string]$BotPath = "$env:USERPROFILE\AppData\Local\BATCRelayBot" ) $ErrorActionPreference = "Stop" Set-Location $BotPath $configPath = Join-Path $BotPath "config.json" if (-not (Test-Path $configPath)) { Write-Host "ERROR: config.json not found at $configPath" -ForegroundColor Red Write-Host "Run Install-BATCRelayBot first or copy config.example.json to config.json" -ForegroundColor Red exit 1 } try { $config = Get-Content $configPath -Raw | ConvertFrom-Json } catch { Write-Host "ERROR: config.json is invalid JSON: $($_.Exception.Message)" -ForegroundColor Red exit 1 } $requiredFields = @("python_path", "voicemeeter_path", "voicemeeter_process_name", "batc_path", "batc_process_name") foreach ($field in $requiredFields) { if (-not $config.$field) { Write-Host "ERROR: field '$field' is missing in config.json" -ForegroundColor Red exit 1 } } function Ensure-Running { param( [string]$DisplayName, [string]$ExePath, [string]$ProcessName, [int]$WaitSecondsAfterStart ) $running = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue if ($running) { Write-Host "$DisplayName is already running." -ForegroundColor Green return } if (-not (Test-Path $ExePath)) { Write-Host "WARNING: $DisplayName not found at $ExePath - skipping." -ForegroundColor Yellow return } Write-Host "$DisplayName is not running - starting..." -ForegroundColor Cyan Start-Process -FilePath $ExePath | Out-Null Write-Host "Waiting $WaitSecondsAfterStart second(s) for $DisplayName to initialize..." -ForegroundColor Cyan Start-Sleep -Seconds $WaitSecondsAfterStart if (-not (Get-Process -Name $ProcessName -ErrorAction SilentlyContinue)) { Write-Host "WARNING: $DisplayName does not appear to be running - please check manually." -ForegroundColor Yellow } } $voicemeeterWait = if ($config.voicemeeter_wait_seconds) { $config.voicemeeter_wait_seconds } else { 6 } $batcWait = if ($config.batc_wait_seconds) { $config.batc_wait_seconds } else { 8 } Write-Host "=== Checking prerequisites ===" -ForegroundColor Cyan Ensure-Running -DisplayName "VoiceMeeter" -ExePath $config.voicemeeter_path ` -ProcessName $config.voicemeeter_process_name -WaitSecondsAfterStart $voicemeeterWait Ensure-Running -DisplayName "BeyondATC" -ExePath $config.batc_path ` -ProcessName $config.batc_process_name -WaitSecondsAfterStart $batcWait Write-Host "" Write-Host "=== Starting bot ===" -ForegroundColor Cyan if (-not (Test-Path $config.python_path)) { Write-Host "ERROR: python_path in config.json does not exist: $($config.python_path)" -ForegroundColor Red exit 1 } $pythonDir = Split-Path -Parent $config.python_path $pythonw = Join-Path $pythonDir "pythonw.exe" if (-not (Test-Path $pythonw)) { Write-Host "pythonw.exe not found - falling back to python.exe (console may briefly appear)." -ForegroundColor Yellow $pythonw = $config.python_path } $logsDir = Join-Path $BotPath "logs" if (-not (Test-Path $logsDir)) { New-Item -Path $logsDir -ItemType Directory | Out-Null } $logFile = Join-Path $logsDir "bot_output.log" $errorLogFile = Join-Path $logsDir "bot_error.log" $pidFile = Join-Path $BotPath "bot.pid" if (Test-Path $pidFile) { $oldPid = Get-Content $pidFile -ErrorAction SilentlyContinue if ($oldPid -and (Get-Process -Id $oldPid -ErrorAction SilentlyContinue)) { Write-Host "Bot is already running (PID $oldPid). Stop it first with Stop-BATCRelayBot." -ForegroundColor Yellow exit 0 } } $process = Start-Process ` -FilePath $pythonw ` -ArgumentList "bot.py" ` -WorkingDirectory $BotPath ` -WindowStyle Hidden ` -RedirectStandardOutput $logFile ` -RedirectStandardError $errorLogFile ` -PassThru $process.Id | Out-File -FilePath $pidFile -Encoding ascii Write-Host "Bot started (PID $($process.Id))." -ForegroundColor Green Write-Host "Output: $logFile" -ForegroundColor Cyan Write-Host "Errors: $errorLogFile" -ForegroundColor Cyan Write-Host "Stop with: Stop-BATCRelayBot" -ForegroundColor Cyan } |