<# S1:IG 用户发一条文本 → iXserver → 第三方 chatbot(echo 自动回复)→ iXserver → IG 用户收到 echo。 前提:.\loop.ps1 up 四个角色都健康,chatbot 以 --auto-reply echo 运行(config\loop.psd1 的 ChatbotAutoReply)。 通过退出 0,失败退出 1 并打印两侧的记录。用法:.\scenarios\s1-ig-text-echo.ps1 [-TimeoutSec 60] #> param([int]$TimeoutSec = 60) $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' $Cfg = Import-PowerShellDataFile (Join-Path $PSScriptRoot '..\config\loop.psd1') $ig = "http://127.0.0.1:$($Cfg.Ports.IgMock)" $cb = "http://127.0.0.1:$($Cfg.Ports.Chatbot)" function Fail([string]$why) { Write-Host "S1 失败:$why" -ForegroundColor Red Write-Host '--- IG 模拟记录' (Invoke-RestMethod "$ig/_api/state").events | ForEach-Object { $_ | ConvertTo-Json -Depth 8 -Compress } | Out-Host Write-Host '--- chatbot 记录(最近 6 条)' # 记录是新的在前 (Invoke-RestMethod "$cb/_api/state").events | Select-Object -First 6 | ForEach-Object { $_ | ConvertTo-Json -Depth 8 -Compress } | Out-Host exit 1 } Invoke-RestMethod "$ig/_api/clear" -Method Post | Out-Null $text = 'loop-s1 ' + [guid]::NewGuid().ToString('N').Substring(0, 8) $sent = Invoke-RestMethod "$ig/_api/send" -Method Post -ContentType 'application/json; charset=utf-8' -Body (@{ kind = 'text'; text = $text } | ConvertTo-Json) if ($sent.event.response.status -ne 200) { Fail "iXserver 收 webhook 返回 $($sent.event.response.status)" } # 出站是异步的:轮询 IG 模拟的 outbound,带上限 $expected = "echo: $text" $deadline = (Get-Date).AddSeconds($TimeoutSec) $hit = $null while (-not $hit -and (Get-Date) -lt $deadline) { $hit = @((Invoke-RestMethod "$ig/_api/state").events | Where-Object { $_.kind -eq 'outbound' -and $_.summary -eq $expected }) | Select-Object -First 1 if (-not $hit) { Start-Sleep -Milliseconds 500 } } if (-not $hit) { Fail "$TimeoutSec 秒内 IG 用户没有收到「$expected」" } if (@($hit.issues).Count) { Fail "出站请求有问题:$($hit.issues -join ';')" } if (-not $hit.tokenPresent) { Fail '出站请求没带 access_token' } # 也要等:iXserver 在 send-txt 应答之前就把消息发到 IG 了,客户端拿到应答才记 reply,会晚上百毫秒 $reply = $null while (-not $reply -and (Get-Date) -lt $deadline.AddSeconds(5)) { $reply = @((Invoke-RestMethod "$cb/_api/state").events | Where-Object { $_.kind -eq 'reply' -and $_.message -eq $expected }) | Select-Object -First 1 if (-not $reply) { Start-Sleep -Milliseconds 200 } } if (-not $reply) { Fail 'chatbot 侧没有对应的回复记录' } if ($reply.response.status -ne 201) { Fail "send-txt 返回 $($reply.response.status)" } Write-Host "S1 通过:「$text」→ ticket $($reply.ticketId) → IG 收到「$expected」" -ForegroundColor Green exit 0