iXserverLoopEnv/scenarios/s8-human-chain.ps1

88 lines
4.4 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<#
S8:人工链路本身(不经第三方 chatbot)。
SCRM 开工(SetSetting IsEnable=false + UpdateCSAvailable 3)→ 客服上线(UserReg + 额度池)
→ 新 IG 用户发消息 → 人工工单,SCRM 在 WebSocket 上收到推送 → 指派 → 打开(验证信息 + 已读)
→ 以客服身份回复 → IG 用户收到 → 结束工单 → SCRM 下班(切回机器人、在线 0),不影响 S1。
前提:.\loop.ps1 up 五个角色都健康。每次用新的 IGSID,保证建出新工单。
通过退出 0,失败退出 1 并打印记录。用法:.\scenarios\s8-human-chain.ps1 [-TimeoutSec 60] [-KeepShift]
#>
param([int]$TimeoutSec = 60, [switch]$KeepShift)
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
$Cfg = Import-PowerShellDataFile (Join-Path $PSScriptRoot '..\config\loop.psd1')
$ig = "http://127.0.0.1:$($Cfg.Ports.IgMock)"
$sc = "http://127.0.0.1:$($Cfg.Ports.ScrmMock)"
function Post([string]$url, $body) {
$bytes = [Text.Encoding]::UTF8.GetBytes(($body | ConvertTo-Json -Compress -Depth 6))
try { return Invoke-RestMethod $url -Method Post -ContentType 'application/json; charset=utf-8' -Body $bytes }
catch {
# 动作失败时模拟方回 502,正文里带着每一步的记录
$resp = $_.Exception.Response
if (-not $resp) { throw }
$reader = New-Object IO.StreamReader($resp.GetResponseStream(), [Text.Encoding]::UTF8)
return ($reader.ReadToEnd() | ConvertFrom-Json)
}
}
function Fail([string]$why) {
Write-Host "S8 失败:$why" -ForegroundColor Red
Write-Host '--- SCRM 模拟记录(最近 15 条)'
(Invoke-RestMethod "$sc/_api/state").events | Select-Object -First 15 | ForEach-Object { ($_ | ConvertTo-Json -Depth 8 -Compress) } | Out-Host
Write-Host '--- IG 模拟记录'
(Invoke-RestMethod "$ig/_api/state").events | ForEach-Object { "{0} {1} {2}" -f $_.kind, $_.igsid, $_.summary } | Out-Host
if (-not $KeepShift) { Post "$sc/_api/shift" @{ on = $false } | Out-Null }
exit 1
}
function Step([string]$action, $body) {
$r = Post "$sc/_api/$action" $body
if (-not $r.ok) { Fail "$action 未成功:$($r.error) $((@($r.calls) | ForEach-Object { $_.api + ' → ' + ($_.response.body.msg) }) -join ';')" }
return $r
}
function Wait-For([string]$what, [scriptblock]$probe) {
$deadline = (Get-Date).AddSeconds($TimeoutSec)
while ((Get-Date) -lt $deadline) {
$hit = & $probe
if ($hit) { return $hit }
Start-Sleep -Milliseconds 500
}
Fail "$TimeoutSec 秒内没等到:$what"
}
$ws = (Invoke-RestMethod "$sc/_api/state").state.ws
if ($ws.status -ne 'logged-in') { Fail "SCRM 模拟的 WebSocket 没登录($($ws.status) $($ws.lastError))" }
Invoke-RestMethod "$sc/_api/clear" -Method Post | Out-Null
Invoke-RestMethod "$ig/_api/clear" -Method Post | Out-Null
Step 'shift' @{ on = $true } | Out-Null
Step 'agent-online' @{} | Out-Null
$igsid = 'loop-s8-' + [guid]::NewGuid().ToString('N').Substring(0, 8)
$sent = Post "$ig/_api/send" @{ kind = 'text'; igsid = $igsid; text = 'S8 想找人工' }
if ($sent.event.response.status -ne 200) { Fail "iXserver 收 webhook 返回 $($sent.event.response.status)" }
# 推送报文没有统一类型字段,按 enduser_openid = IGSID 认出这张新工单
$ticketId = Wait-For 'SCRM 收到这位 IG 用户的工单推送' {
$push = @((Invoke-RestMethod "$sc/_api/state").events | Where-Object { $_.kind -eq 'push' -and (($_.parsed | ConvertTo-Json -Depth 8 -Compress) -match [regex]::Escape($igsid)) }) | Select-Object -First 1
if ($push) { $push.ticketIds | Select-Object -First 1 }
}
Step 'assign' @{ ticket_id = $ticketId } | Out-Null
Step 'open' @{ ticket_id = $ticketId } | Out-Null
$replyText = 'S8 客服回复 ' + [guid]::NewGuid().ToString('N').Substring(0, 6)
Step 'reply' @{ ticket_id = $ticketId; text = $replyText } | Out-Null
$out = Wait-For "IG 用户收到「$replyText」" {
@((Invoke-RestMethod "$ig/_api/state").events | Where-Object { $_.kind -eq 'outbound' -and $_.igsid -eq $igsid -and $_.summary -eq $replyText }) | Select-Object -First 1
}
if (@($out.issues).Count) { Fail "出站请求有问题:$($out.issues -join ';')" }
Step 'complete' @{ ticket_id = $ticketId } | Out-Null
if (-not $KeepShift) { Step 'shift' @{ on = $false } | Out-Null }
Write-Host "S8 通过:$igsid → 人工工单 $ticketId → SCRM 收到推送、指派、回复 → IG 收到「$replyText」→ 已结束" -ForegroundColor Green
exit 0