$ErrorActionPreference = "Stop" $BaseUrl = 'https://contact.robinmollah.com' $ProfileText = "" $SessionId = "" $ClientToken = "" $Cursor = 0 $Running = $true $Transcript = New-Object System.Collections.Generic.List[string] $TempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("chat-with-robin-" + [guid]::NewGuid().ToString()) function Test-InteractiveConsole { try { $null = $Host.UI.RawUI return $true } catch { return $false } } function Append-Transcript([string]$Line) { $script:Transcript.Add($Line) | Out-Null } function Write-Banner { Write-Host @" ======================================== ____ ___ ____ ___ _ _ | _ \ / _ \| __ )_ _| \ | | | |_) | | | | _ \| || \| | | _ <| |_| | |_) | || |\ | |_| \_\\___/|____/___|_| \_| __ __ ___ _ _ _ _ | \/ |/ _ \| | | | / \ | | | |\/| | | | | | | | / _ \| | | | | | |_| | |___| |___ / ___ \ | |_| |_|\___/|_____|_____/_/ \_\_| ======================================== "@ } function Draw-Ui { Clear-Host Write-Banner Write-Host "" Write-Host "Direct terminal contact with Robin." Write-Host "Use :about if you want the full profile and links." Write-Host "" Write-Host "----------------------------------------" Write-Host " Conversation" Write-Host "----------------------------------------" if ($script:Transcript.Count -gt 0) { foreach ($line in $script:Transcript) { Write-Host $line } } else { Write-Host "No messages yet. Type something and press Enter." } Write-Host "" Write-Host "Commands: :help :about :clear :quit" Write-Host "" } function Fetch-Profile { $script:ProfileText = Invoke-RestMethod -Uri "$BaseUrl/api/profile?format=text" -Method Get } function Create-Session([string]$Name) { $body = @{ name = $Name } | ConvertTo-Json -Compress $response = Invoke-RestMethod -Uri "$BaseUrl/api/session" -Method Post -ContentType "application/json" -Body $body $script:SessionId = [string]$response.sessionId $script:ClientToken = [string]$response.clientToken $script:Cursor = [int]$response.cursor } function Get-Headers { return @{ Authorization = "Bearer $script:ClientToken" } } function Fetch-Events([int]$WaitFlag = 1) { $response = Invoke-RestMethod -Uri "$BaseUrl/api/session/$SessionId/events?cursor=$Cursor&wait=$WaitFlag" -Method Get -Headers (Get-Headers) foreach ($event in $response.events) { $timestamp = [string]$event.timestamp $text = [string]$event.text switch ([string]$event.kind) { "info" { Append-Transcript "[$timestamp] info: $text" } "visitor_message_ack" { Append-Transcript "[$timestamp] you: $text" } "robin_message" { Append-Transcript "[$timestamp] robin: $text" } "session_closed" { Append-Transcript "[$timestamp] session: $text" $script:Running = $false } default { Append-Transcript "[$timestamp] $([string]$event.kind): $text" } } } $script:Cursor = [int]$response.nextCursor } function Post-Message([string]$Text) { $body = @{ text = $Text } | ConvertTo-Json -Compress Invoke-RestMethod -Uri "$BaseUrl/api/session/$SessionId/message" -Method Post -ContentType "application/json" -Headers (Get-Headers) -Body $body | Out-Null } function Send-MessageWithProgress([string]$Text) { $job = Start-Job -ScriptBlock { param($Uri, $Token, $Payload) $headers = @{ Authorization = "Bearer $Token" } Invoke-RestMethod -Uri $Uri -Method Post -ContentType "application/json" -Headers $headers -Body $Payload | Out-Null } -ArgumentList "$BaseUrl/api/session/$SessionId/message", $script:ClientToken, (@{ text = $Text } | ConvertTo-Json -Compress) $percent = 10 while ($job.State -eq "Running") { Write-Progress -Activity "Sending message" -Status "Contacting Robin" -PercentComplete $percent Start-Sleep -Milliseconds 120 $percent += 8 if ($percent -gt 90) { $percent = 25 } } try { Receive-Job -Job $job -Wait -ErrorAction Stop | Out-Null Write-Progress -Activity "Sending message" -Completed return $true } catch { Write-Progress -Activity "Sending message" -Completed return $false } finally { Remove-Job -Job $job -Force -ErrorAction SilentlyContinue } } function Print-Help { Append-Transcript "[local] Commands:" Append-Transcript "[local] :help Show available commands" Append-Transcript "[local] :about Reprint profile information" Append-Transcript "[local] :clear Clear the transcript" Append-Transcript "[local] :quit Close this session" } function Handle-Line([string]$Line) { switch ($Line) { ":help" { Print-Help } ":about" { Append-Transcript "[local] Profile" foreach ($aboutLine in ($script:ProfileText -split "\r?\n")) { Append-Transcript "[local] $aboutLine" } } ":clear" { $script:Transcript.Clear() } ":quit" { $script:Running = $false Append-Transcript "[local] Closing session." Draw-Ui } "" { } default { if (Send-MessageWithProgress $Line) { Fetch-Events } else { Append-Transcript "[local] Failed to send message." } } } } function Main-Loop { while ($script:Running) { Fetch-Events 0 Draw-Ui $line = Read-Host ">" Handle-Line $line.Trim() } } function Close-Session { if ($script:SessionId -and $script:ClientToken) { try { Invoke-RestMethod -Uri "$BaseUrl/api/session/$SessionId/close" -Method Post -Headers (Get-Headers) | Out-Null } catch { } } if (Test-Path $script:TempDir) { Remove-Item -Path $script:TempDir -Recurse -Force -ErrorAction SilentlyContinue } } function Bootstrap { if (-not (Test-InteractiveConsole)) { throw "This script needs an interactive PowerShell console." } New-Item -ItemType Directory -Path $script:TempDir -Force | Out-Null Fetch-Profile Draw-Ui $name = "" while ([string]::IsNullOrWhiteSpace($name)) { $name = Read-Host "Your name" $name = $name.Trim() } Create-Session $name Fetch-Events Draw-Ui Main-Loop } try { Bootstrap } finally { Close-Session Write-Host "" }