Add all 44 scripts, update CI: error severity baseline, PowerShell validation, multi-distro testing
Amp-Thread-ID: https://ampcode.com/threads/T-019cc404-c628-759e-a50b-f5eeea35b91f Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
#############################################################
|
||||
#### ntfy Desktop Client Setup for Windows ####
|
||||
#### Subscribe to ntfy push notifications with Windows ####
|
||||
#### toast notifications ####
|
||||
#### ####
|
||||
#### Author: Phil Connor ####
|
||||
#### Contact: contact@mylinux.work ####
|
||||
#### License: MIT ####
|
||||
#### Version: 1.0 ####
|
||||
#### ####
|
||||
#### Usage: .\ntfy-client-setup-windows.ps1 ####
|
||||
#############################################################
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# --- Configuration ---
|
||||
$NtfyVersion = "2.8.0"
|
||||
$InstallDir = "$env:LOCALAPPDATA\ntfy"
|
||||
$ConfigDir = "$env:APPDATA\ntfy"
|
||||
|
||||
# --- Interactive Prompts ---
|
||||
Write-Host ""
|
||||
Write-Host "=== ntfy Desktop Notifications Setup ===" -ForegroundColor Cyan
|
||||
Write-Host "Installing for user: $env:USERNAME"
|
||||
Write-Host ""
|
||||
|
||||
# Server URL
|
||||
$ServerUrl = Read-Host "Enter your ntfy server URL (e.g. https://ntfy.example.com)"
|
||||
$ServerUrl = $ServerUrl.TrimEnd("/")
|
||||
if ([string]::IsNullOrWhiteSpace($ServerUrl)) {
|
||||
Write-Host "ERROR: Server URL is required." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Access token (optional — some servers allow anonymous access)
|
||||
$Token = Read-Host "Enter your access token (leave blank if not required)"
|
||||
|
||||
# Topics
|
||||
$topicInput = Read-Host "Enter topics to subscribe to, comma-separated (e.g. alerts-critical,alerts-all)"
|
||||
if ([string]::IsNullOrWhiteSpace($topicInput)) {
|
||||
Write-Host "ERROR: At least one topic is required." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
$Topics = $topicInput -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" }
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Server: $ServerUrl" -ForegroundColor White
|
||||
Write-Host "Topics: $($Topics -join ', ')" -ForegroundColor White
|
||||
Write-Host "Token: $(if ($Token) { '********' } else { '(none)' })" -ForegroundColor White
|
||||
Write-Host ""
|
||||
|
||||
# --- Create directories ---
|
||||
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
|
||||
New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null
|
||||
|
||||
# --- Download ntfy if not already installed ---
|
||||
if (Test-Path "$InstallDir\ntfy.exe") {
|
||||
Write-Host "ntfy already installed at: $InstallDir\ntfy.exe" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "Downloading ntfy v$NtfyVersion..."
|
||||
$downloadUrl = "https://github.com/binwiederhier/ntfy/releases/download/v$NtfyVersion/ntfy_${NtfyVersion}_windows_amd64.zip"
|
||||
$zipPath = "$env:TEMP\ntfy.zip"
|
||||
Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath
|
||||
|
||||
Write-Host "Extracting..."
|
||||
$extractPath = "$env:TEMP\ntfy_extract"
|
||||
Remove-Item -Path $extractPath -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Expand-Archive -Path $zipPath -DestinationPath $extractPath -Force
|
||||
Remove-Item $zipPath
|
||||
|
||||
# Find the exe (may be in a subfolder)
|
||||
$ntfyExe = Get-ChildItem -Path $extractPath -Recurse -Filter "ntfy.exe" | Select-Object -First 1
|
||||
if ($ntfyExe) {
|
||||
Copy-Item -Path $ntfyExe.FullName -Destination "$InstallDir\ntfy.exe" -Force
|
||||
} else {
|
||||
Write-Host "ERROR: Could not find ntfy.exe in downloaded archive." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
Remove-Item -Path $extractPath -Recurse -Force -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Host "Installed to: $InstallDir\ntfy.exe" -ForegroundColor Green
|
||||
}
|
||||
Write-Host ""
|
||||
|
||||
# --- Create client.yml config ---
|
||||
$clientYml = @"
|
||||
default-host: $ServerUrl
|
||||
"@
|
||||
|
||||
if ($Token) {
|
||||
$clientYml += "`ndefault-token: $Token"
|
||||
}
|
||||
|
||||
$clientYmlPath = "$ConfigDir\client.yml"
|
||||
$clientYml | Out-File -FilePath $clientYmlPath -Encoding UTF8
|
||||
Write-Host "Client config saved to: $clientYmlPath" -ForegroundColor Green
|
||||
|
||||
# --- Build topic URLs ---
|
||||
$topicUrls = @()
|
||||
foreach ($topic in $Topics) {
|
||||
$topicUrls += "$ServerUrl/$topic"
|
||||
}
|
||||
$topicUrlsString = $topicUrls -join " "
|
||||
|
||||
# --- Create PowerShell notification script ---
|
||||
# Build the token environment line only if a token was provided
|
||||
$tokenLine = ""
|
||||
if ($Token) {
|
||||
$tokenLine = "`$env:NTFY_TOKEN = `"$Token`""
|
||||
}
|
||||
|
||||
$psScriptContent = @"
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
|
||||
# Create a persistent notification icon in the system tray
|
||||
`$global:notifyIcon = New-Object System.Windows.Forms.NotifyIcon
|
||||
`$global:notifyIcon.Icon = [System.Drawing.SystemIcons]::Information
|
||||
`$global:notifyIcon.Visible = `$true
|
||||
`$global:notifyIcon.Text = "ntfy alerts"
|
||||
|
||||
function Show-Notification {
|
||||
param([string]`$Title, [string]`$Message, [int]`$Priority)
|
||||
|
||||
# Map ntfy priority levels to Windows balloon icon types
|
||||
# 1 (min), 2 (low) -> None
|
||||
# 3 (default) -> Info
|
||||
# 4 (high), 5 (max) -> Error
|
||||
`$icon = [System.Windows.Forms.ToolTipIcon]::Info
|
||||
if (`$Priority -ge 4) { `$icon = [System.Windows.Forms.ToolTipIcon]::Error }
|
||||
elseif (`$Priority -le 2) { `$icon = [System.Windows.Forms.ToolTipIcon]::None }
|
||||
|
||||
`$global:notifyIcon.BalloonTipIcon = `$icon
|
||||
`$global:notifyIcon.BalloonTipTitle = `$Title
|
||||
`$global:notifyIcon.BalloonTipText = `$Message
|
||||
`$global:notifyIcon.ShowBalloonTip(30000)
|
||||
}
|
||||
|
||||
# Set access token if configured
|
||||
$tokenLine
|
||||
`$ntfyExe = "$InstallDir\ntfy.exe"
|
||||
|
||||
# Subscribe and process JSON output line by line
|
||||
& `$ntfyExe subscribe $topicUrlsString 2>&1 | ForEach-Object {
|
||||
`$line = `$_
|
||||
if (`$line -match '"event":"message"') {
|
||||
try {
|
||||
`$json = `$line | ConvertFrom-Json
|
||||
`$title = if (`$json.title) { `$json.title } else { `$json.topic }
|
||||
`$message = `$json.message
|
||||
`$priority = if (`$json.priority) { `$json.priority } else { 3 }
|
||||
Show-Notification -Title `$title -Message `$message -Priority `$priority
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
|
||||
`$global:notifyIcon.Dispose()
|
||||
"@
|
||||
|
||||
$psScriptPath = "$ConfigDir\run-subscribe.ps1"
|
||||
$psScriptContent | Out-File -FilePath $psScriptPath -Encoding UTF8
|
||||
Write-Host "Notification script saved to: $psScriptPath" -ForegroundColor Green
|
||||
|
||||
# --- Create VBS wrapper for hidden startup (no console window) ---
|
||||
$vbsContent = @"
|
||||
Set WshShell = CreateObject("WScript.Shell")
|
||||
WshShell.Run "powershell -ExecutionPolicy Bypass -WindowStyle Hidden -File ""$psScriptPath""", 0
|
||||
Set WshShell = Nothing
|
||||
"@
|
||||
|
||||
$vbsPath = "$ConfigDir\run-subscribe-hidden.vbs"
|
||||
$vbsContent | Out-File -FilePath $vbsPath -Encoding ASCII
|
||||
Write-Host "Hidden launcher saved to: $vbsPath" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# --- Create startup shortcut ---
|
||||
Write-Host "Creating startup shortcut..."
|
||||
$startupPath = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup"
|
||||
$shortcutPath = "$startupPath\ntfy-subscribe.lnk"
|
||||
|
||||
$shell = New-Object -ComObject WScript.Shell
|
||||
$shortcut = $shell.CreateShortcut($shortcutPath)
|
||||
$shortcut.TargetPath = "wscript.exe"
|
||||
$shortcut.Arguments = "`"$vbsPath`""
|
||||
$shortcut.WorkingDirectory = $ConfigDir
|
||||
$shortcut.WindowStyle = 7 # Minimized
|
||||
$shortcut.Description = "ntfy notification subscriber"
|
||||
$shortcut.Save()
|
||||
|
||||
Write-Host "Startup shortcut created at: $shortcutPath" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# --- Start the subscriber now ---
|
||||
Write-Host "Starting ntfy subscriber..."
|
||||
|
||||
# Stop any existing ntfy or subscriber processes
|
||||
Stop-Process -Name ntfy -ErrorAction SilentlyContinue
|
||||
Get-Process powershell -ErrorAction SilentlyContinue | Where-Object { $_.Id -ne $PID } | ForEach-Object {
|
||||
try {
|
||||
$cmdLine = (Get-CimInstance Win32_Process -Filter "ProcessId = $($_.Id)" -ErrorAction SilentlyContinue).CommandLine
|
||||
if ($cmdLine -like "*run-subscribe*") { Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue }
|
||||
} catch {}
|
||||
}
|
||||
Start-Sleep -Seconds 1
|
||||
|
||||
$process = Start-Process -FilePath "powershell" `
|
||||
-ArgumentList @("-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-File", $psScriptPath) `
|
||||
-WindowStyle Hidden `
|
||||
-PassThru
|
||||
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
# --- Print status and management commands ---
|
||||
if ($process -and !$process.HasExited) {
|
||||
Write-Host ""
|
||||
Write-Host "=== Setup Complete ===" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "ntfy is running and will start automatically on login." -ForegroundColor Green
|
||||
Write-Host "You should see Windows toast notifications when messages arrive."
|
||||
Write-Host ""
|
||||
Write-Host "Management commands (run in PowerShell):" -ForegroundColor Cyan
|
||||
Write-Host " Check status: Get-Process ntfy -ErrorAction SilentlyContinue"
|
||||
Write-Host " Stop: Stop-Process -Name ntfy"
|
||||
Write-Host " Start manually: wscript.exe '$vbsPath'"
|
||||
Write-Host " Edit config: notepad '$clientYmlPath'"
|
||||
Write-Host " Edit topics: notepad '$psScriptPath'"
|
||||
Write-Host ""
|
||||
} else {
|
||||
Write-Host ""
|
||||
Write-Host "WARNING: ntfy may not have started correctly." -ForegroundColor Yellow
|
||||
Write-Host "Try running manually: wscript.exe '$vbsPath'"
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
Write-Host "To test, send a notification from another machine:" -ForegroundColor Cyan
|
||||
Write-Host " curl -d 'Test message' $ServerUrl/$($Topics[0])"
|
||||
Write-Host ""
|
||||
Reference in New Issue
Block a user