pubg/discord/report_to_discord.ps1
2025-04-15 17:12:33 +02:00

196 lines
No EOL
8.5 KiB
PowerShell

# --- Script Setup ---
# Note: Transcript path seems incorrect, should likely be specific to this script.
# Consider changing to '/var/log/dtch/report_to_discord.log' or similar.
Start-Transcript -Path '/var/log/dtch/report_to_discord.log' -Append
Write-Output "Starting report_to_discord script at $(Get-Date)"
Write-Output "Running from: $(Get-Location)"
# Determine script root directory reliably
if ($PSScriptRoot) {
$scriptRoot = $PSScriptRoot
} else {
$scriptRoot = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
Write-Warning "PSScriptRoot not defined, using calculated path: $scriptRoot"
}
Write-Output "Script root identified as: $scriptRoot"
# Define paths using Join-Path
$includesPath = Join-Path -Path $scriptRoot -ChildPath "..\includes\ps1"
$discordConfigPath = Join-Path -Path $scriptRoot -ChildPath "config.php" # Config is in the same dir
$dataPath = Join-Path -Path $scriptRoot -ChildPath "..\data"
$lastStatsJsonPath = Join-Path -Path $dataPath -ChildPath "player_last_stats.json"
# --- Locking ---
$lockFilePath = Join-Path -Path $includesPath -ChildPath "lockfile.ps1"
if (-not (Test-Path -Path $lockFilePath -PathType Leaf)) {
Write-Error "Lockfile script not found at '$lockFilePath'. Cannot proceed."
Stop-Transcript
exit 1
}
. $lockFilePath
New-Lock -by "report_to_discord" -ErrorAction Stop # Stop if locking fails
# --- Main Logic in Try/Finally for Lock Removal ---
try {
# --- Helper Function ---
# Checks if K/D values are valid numbers (not NaN or Infinity)
function Test-IsValidKdEntry {
param($entry)
# Check if properties exist and are numeric before comparison
$kdHValid = $entry.PSObject.Properties.Name -contains 'KD_H' -and $entry.KD_H -is [double] -and -not [double]::IsNaN($entry.KD_H) -and -not [double]::IsInfinity($entry.KD_H)
$kdAllValid = $entry.PSObject.Properties.Name -contains 'KD_ALL' -and $entry.KD_ALL -is [double] -and -not [double]::IsNaN($entry.KD_ALL) -and -not [double]::IsInfinity($entry.KD_ALL)
return $kdHValid -and $kdAllValid
}
# --- Configuration Loading ---
$webhookUrl = $null
if (Test-Path -Path $discordConfigPath -PathType Leaf) {
try {
$fileContent = Get-Content -Path $discordConfigPath -Raw -ErrorAction Stop
# Corrected regex for webhookurl
if ($fileContent -match '^\s*\$webhookurl\s*=\s*''([^'']+)''') {
$webhookUrl = $matches[1]
Write-Output "Discord webhook URL loaded successfully."
} else {
Write-Warning "Webhook URL pattern not found in '$discordConfigPath'."
}
} catch {
Write-Warning "Failed to read '$discordConfigPath'. Error: $($_.Exception.Message)"
}
} else {
Write-Warning "Discord config file not found at '$discordConfigPath'."
}
if (-not $webhookUrl) {
Write-Error "Discord webhook URL could not be loaded. Cannot send report."
throw "Missing Webhook URL" # Throw to trigger finally block
}
# --- Load Stats Data ---
$statsData = $null
if (Test-Path -Path $lastStatsJsonPath -PathType Leaf) {
try {
$statsData = Get-Content -Path $lastStatsJsonPath | ConvertFrom-Json -ErrorAction Stop
if ($null -eq $statsData) {
Write-Error "Failed to parse stats data from '$lastStatsJsonPath'. Cannot generate report."
throw "Invalid Stats Data"
}
Write-Output "Successfully loaded player stats data."
} catch {
Write-Error "Error reading '$lastStatsJsonPath': $($_.Exception.Message). Cannot generate report."
throw $_
}
} else {
Write-Error "Player stats file not found at '$lastStatsJsonPath'. Cannot generate report."
throw "Missing Stats File"
}
# --- Process Stats ---
Write-Output "Processing stats..."
# Safely access the 'all' category and filter valid entries
$filteredAllStats = @()
if ($statsData.PSObject.Properties.Name -contains 'all' -and $statsData.all -is [array]) {
$filteredAllStats = $statsData.all | Where-Object { Test-IsValidKdEntry $_ }
Write-Output "Found $($filteredAllStats.Count) valid entries in 'all' category."
} else {
Write-Warning "Stats data does not contain a valid 'all' array. Report might be incomplete."
}
# --- Find Top Players (Handle Empty/Null Cases) ---
# Helper to safely get top player stat
function Get-TopStat {
param(
[array]$Data,
[string]$Property,
[string]$DefaultName = "N/A",
[string]$DefaultStat = "N/A"
)
$sorted = $Data | Sort-Object $Property -Descending -ErrorAction SilentlyContinue
if ($sorted -and $sorted.Count -gt 0) {
# Ensure the property exists on the top object before accessing
$topEntry = $sorted[0]
$playerName = if ($topEntry.PSObject.Properties.Name -contains 'playername') { $topEntry.playername } else { $DefaultName }
$statValue = if ($topEntry.PSObject.Properties.Name -contains $Property) { $topEntry.$Property } else { $DefaultStat }
# Format numeric stats if needed (e.g., K/D)
if ($Property -like "KD*" -and $statValue -is [double]) { $statValue = "{0:N2}" -f $statValue }
return @{ 'name' = $playerName; 'stat' = $statValue }
} else {
return @{ 'name' = $DefaultName; 'stat' = $DefaultStat }
}
}
$mostKills = Get-TopStat -Data $filteredAllStats -Property 'kills'
$mostDeaths = Get-TopStat -Data $filteredAllStats -Property 'deaths'
$mostHumanKills = Get-TopStat -Data $filteredAllStats -Property 'humankills'
$mostKdH = Get-TopStat -Data $filteredAllStats -Property 'KD_H'
$mostKdAll = Get-TopStat -Data $filteredAllStats -Property 'KD_ALL'
$mostMatches = Get-TopStat -Data $filteredAllStats -Property 'matches'
Write-Output "Determined top players for report."
# --- Format Discord Message ---
# Using PowerShell multi-line string with variable substitution
$reportContent = @"
:rocket: Het maandelijks raportje :rocket:
Hey toppers!
Laten we eens duiken in de cijfers van onze supergamers van de afgelopen maand:
:dart: Meeste Kills:
Hats off voor **$($mostKills.name)**! Met **$($mostKills.stat)** kills is hij/zij onze scherpschutter van de maand!
:skull_crossbones: Meeste Deaths:
Oei, oei, oei... **$($mostDeaths.name)** is helaas het vaakst naar het hiernamaals gestuurd met **$($mostDeaths.stat)** deaths. Kop op, volgende keer beter!
:robot: Meeste Humankills:
Watch out! We hebben een Terminator onder ons. Hoedje af voor **$($mostHumanKills.name)** met **$($mostHumanKills.stat)** humankills!
:bar_chart: Beste KD Ratio (Alle vijanden):
De onevenaarbare **$($mostKdAll.name)** heeft een KD van **$($mostKdAll.stat)** ! Niet slecht, toch? 😉
:adult: Beste KD Ratio (Alleen menselijke spelers):
Opgelet, gamers! **$($mostKdH.name)** heeft een KD van **$($mostKdH.stat)** tegen andere spelers! Wie daagt hem/haar uit?
:video_game: Meeste Matches:
Onze meest toegewijde gamer, **$($mostMatches.name)**, heeft maar liefst **$($mostMatches.stat)** matches gespeeld. Ga zo door!
Da's het voor nu, gamers! Blijf schieten, blijf lachen en tot het volgende rapportje!
High fives en knuffels (virtueel, natuurlijk),
Het Gaming Team
Meer stats zijn hier te vinden : https://lanta.eu/DTCH
"@
Write-Output "Formatted Discord message content."
# Write-Verbose $reportContent # Uncomment to see the full message in verbose logs
# --- Send to Discord ---
$payload = @{
content = $reportContent
# username = "Stats Bot" # Optional: Override bot name
# avatar_url = "" # Optional: Override bot avatar
} | ConvertTo-Json -Depth 3 # Depth 3 should be sufficient
Write-Output "Sending report to Discord webhook..."
try {
Invoke-RestMethod -Uri $webhookUrl -Method Post -Body $payload -ContentType 'application/json' -ErrorAction Stop
Write-Output "Report successfully sent to Discord."
} catch {
$errorMessage = $_.Exception.Message
Write-Error "Failed to send report to Discord. Error: $errorMessage"
# Consider logging the failed payload or response details if available
# Write-Warning "Payload: $payload"
}
} # End Main Try Block
finally {
# --- Cleanup ---
Write-Output "Script finished at $(Get-Date)."
Remove-Lock # Ensure lock is always removed
Stop-Transcript
}