69 lines
3.9 KiB
PowerShell
69 lines
3.9 KiB
PowerShell
<#
|
||
S1:IG 用户发一条文本 → iXserver → 第三方 chatbot(echo 自动回复)→ iXserver → IG 用户收到 echo。
|
||
每次用新的 IGSID,先走完条款同意(_lib.ps1 的 Complete-LoopTnC)。
|
||
前提:.\loop.ps1 up 各角色都健康,chatbot 以 --auto-reply echo 运行(config\loop.psd1 的 ChatbotAutoReply)。
|
||
通过退出 0,失败退出 1 并打印两侧的记录;两种情况都在 run\reports\ 生成场景报告(观察台在跑时)。
|
||
用法:.\scenarios\s1-ig-text-echo.ps1 [-TimeoutSec 60] [-NoReport]
|
||
#>
|
||
param([int]$TimeoutSec = 60, [switch]$NoReport)
|
||
$ErrorActionPreference = 'Stop'
|
||
$ProgressPreference = 'SilentlyContinue'
|
||
$LoopNoReport = [bool]$NoReport
|
||
. (Join-Path $PSScriptRoot '_lib.ps1')
|
||
$Cfg = $LoopCfg
|
||
$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
|
||
Add-LoopStep $why $false
|
||
Save-LoopReport -Passed $false -Reason $why
|
||
exit 1
|
||
}
|
||
|
||
Start-LoopRun 'S1' 'IG 文本 → 第三方 echo → IG'
|
||
Invoke-RestMethod "$ig/_api/clear" -Method Post | Out-Null
|
||
$igsid = 'loop-s1-' + [guid]::NewGuid().ToString('N').Substring(0, 8)
|
||
$err = Complete-LoopTnC $igsid $TimeoutSec
|
||
if ($err) { Fail $err }
|
||
$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 ([Text.Encoding]::UTF8.GetBytes((@{ kind = 'text'; igsid = $igsid; text = $text } | ConvertTo-Json)))
|
||
if ($sent.event.response.status -ne 200) { Fail "iXserver 收 webhook 返回 $($sent.event.response.status)" }
|
||
Add-LoopStep 'iXserver 收下 webhook' $true "「$text」HTTP 200"
|
||
|
||
# 出站是异步的:轮询 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 $_.igsid -eq $igsid -and $_.summary -eq $expected }) | Select-Object -First 1
|
||
if (-not $hit) { Start-Sleep -Milliseconds 500 }
|
||
}
|
||
if (-not $hit) { Fail "$TimeoutSec 秒内 iXserver 没有向 IG 用户发出「$expected」" }
|
||
Add-LoopStep 'iXserver 向 IG 用户发出 echo' $true $expected
|
||
if (@($hit.issues).Count) { Fail "出站请求有问题:$($hit.issues -join ';')" }
|
||
if (-not $hit.tokenPresent) { Fail '出站请求没带 access_token' }
|
||
Add-LoopStep '出站请求带 token、报文无问题' $true
|
||
if ($hit.response.status -ne 200) { Fail "Graph 应答 $($hit.response.status)(IG 模拟档位 $($hit.response.mode)),用户实际没收到" }
|
||
Add-LoopStep 'Graph 应答 200,用户收到' $true $hit.response.messageId
|
||
|
||
# 也要等: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 侧没有对应的回复记录' }
|
||
Set-LoopTicket $reply.ticketId
|
||
if ($reply.response.status -ne 201) { Fail "send-txt 返回 $($reply.response.status)" }
|
||
Add-LoopStep '第三方 send-txt 201' $true "ticket $($reply.ticketId)"
|
||
|
||
Write-Host "S1 通过:「$text」→ ticket $($reply.ticketId) → IG 收到「$expected」" -ForegroundColor Green
|
||
Save-LoopReport -Passed $true
|
||
exit 0
|