This commit is contained in:
oliver
2026-08-28 10:11:11 -03:00
parent f533ff8e36
commit 585951c8ce
1380 changed files with 1540268 additions and 0 deletions
@@ -0,0 +1,88 @@
#requires -version 5.1
<#
kie-image.ps1 - generate hero/OG images via kie.ai (z-image by default).
Loads KIE_API_KEY from .env.local at repo root (or $env:KIE_API_KEY).
Usage:
powershell -File seo-audit-2026-05-27\scripts\kie-image.ps1 -Prompt "..." -OutPath "images/<slug>-hero.png" [-Model z-image] [-Aspect 16:9] [-Resolution 2K]
Models: z-image (default, fast), nano-banana-2 (premium fallback), nano-banana-pro.
Mechanism: POST /api/v1/jobs/createTask with callBackUrl -> ntfy.sh topic -> poll for result.
Note: The old /api/v1/jobs/getTaskDetails polling endpoint no longer exists (API change 2026-05).
Results are now delivered via callBackUrl (webhook). This script uses ntfy.sh as a
free anonymous webhook receiver since no public server is required.
#>
param(
[Parameter(Mandatory)][string]$Prompt,
[Parameter(Mandatory)][string]$OutPath,
[string]$Model = "z-image",
[string]$Aspect = "16:9",
[string]$Resolution = "2K",
[string]$Format = "png",
[int]$TimeoutSec = 300
)
$ErrorActionPreference = "Stop"
$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
if(-not $env:KIE_API_KEY){
$envFile = Join-Path $repoRoot ".env.local"
if(Test-Path $envFile){
$line = Get-Content $envFile -ErrorAction SilentlyContinue | Where-Object { $_ -match '^KIE_API_KEY=' } | Select-Object -First 1
if($line){ $env:KIE_API_KEY = ($line -replace '^KIE_API_KEY=','').Trim('"',"'") }
}
}
if(-not $env:KIE_API_KEY){ throw "KIE_API_KEY not set (env var or .env.local)" }
# Generate unique ntfy.sh topic for callback
$ntfyTopic = "kie-img-$(Get-Date -Format 'yyyyMMddHHmmss')-$(Get-Random -Maximum 9999)"
$callBackUrl = "https://ntfy.sh/$ntfyTopic"
$headers = @{ Authorization = "Bearer $($env:KIE_API_KEY)"; 'Content-Type' = 'application/json' }
$body = @{
model = $Model
input = @{ prompt = $Prompt; aspect_ratio = $Aspect; resolution = $Resolution; output_format = $Format }
callBackUrl = $callBackUrl
} | ConvertTo-Json -Depth 6
Write-Host "[kie-image] submit model=$Model aspect=$Aspect res=$Resolution"
Write-Host "[kie-image] callback=$callBackUrl"
$create = Invoke-RestMethod -Uri 'https://api.kie.ai/api/v1/jobs/createTask' -Method POST -Headers $headers -Body $body
if($create.code -ne 200){ throw "createTask failed: $($create | ConvertTo-Json -Depth 5 -Compress)" }
$taskId = $create.data.taskId
Write-Host "[kie-image] taskId=$taskId polling via ntfy.sh..."
$deadline = (Get-Date).AddSeconds($TimeoutSec)
$imageUrl = $null
while((Get-Date) -lt $deadline){
Start-Sleep -Seconds 8
try {
$r = Invoke-WebRequest -Uri "https://ntfy.sh/$ntfyTopic/json?poll=1" -UseBasicParsing -ErrorAction Stop
$text = [System.Text.Encoding]::UTF8.GetString($r.RawContentStream.ToArray())
# Parse NDJSON lines for kie.ai callback
$lines = $text -split '[\r\n]+' | Where-Object { $_ -match '"event":"message"' }
foreach ($line in $lines) {
try {
$msg = $line | ConvertFrom-Json
$payload = $msg.message | ConvertFrom-Json
if ($payload.code -eq 200 -and $payload.data.taskId -eq $taskId) {
$state = $payload.data.state
Write-Host "[kie-image] state=$state"
if ($state -eq 'success') {
$rj = $payload.data.resultJson | ConvertFrom-Json
$imageUrl = $rj.resultUrls[0]
break
}
if ($state -eq 'failed' -or $state -eq 'error') {
throw "task failed: $($payload | ConvertTo-Json -Depth 5 -Compress)"
}
}
} catch { }
}
} catch { }
if ($imageUrl) { break }
}
if(-not $imageUrl){ throw "timed out after $TimeoutSec s waiting for task $taskId" }
$outFull = Join-Path $repoRoot $OutPath
$outDir = Split-Path -Parent $outFull
if($outDir -and -not (Test-Path $outDir)){ New-Item -ItemType Directory -Force -Path $outDir | Out-Null }
Invoke-WebRequest -Uri $imageUrl -OutFile $outFull -UseBasicParsing
Write-Host "[kie-image] saved: $outFull"
Write-Output $outFull