Add SandwichReminder-AutoOrder feature for automated sandwich ordering and enhance SandwichReminder logic
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
# SandwichAutoOrder.ps1 — best-effort browser keyboard automation for personal sandwich flow.
|
||||
|
||||
function Invoke-AppActivateBestEffort {
|
||||
param(
|
||||
[Parameter(Mandatory)]$Shell,
|
||||
[Parameter(Mandatory)][string[]]$TitleCandidates,
|
||||
[int]$TimeoutMs = 10000,
|
||||
[int]$RetryDelayMs = 300
|
||||
)
|
||||
|
||||
$deadline = (Get-Date).AddMilliseconds($TimeoutMs)
|
||||
$candidates = @($TitleCandidates | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
|
||||
|
||||
do {
|
||||
foreach ($candidate in $candidates) {
|
||||
if ($Shell.AppActivate($candidate)) {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
Start-Sleep -Milliseconds $RetryDelayMs
|
||||
} while ((Get-Date) -lt $deadline)
|
||||
|
||||
return $false
|
||||
}
|
||||
|
||||
function Invoke-SandwichAutoOrderFlow {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory)][hashtable]$AutoOrderConfig,
|
||||
[Parameter(Mandatory)][string]$FallbackUrl,
|
||||
[string]$FeatureName = 'SandwichReminder-AutoOrder'
|
||||
)
|
||||
|
||||
$baseUrl = [string]$AutoOrderConfig['baseUrl']
|
||||
if ([string]::IsNullOrWhiteSpace($baseUrl)) { $baseUrl = 'https://ylos-kitchen.unipage.eu' }
|
||||
|
||||
$itemId = [string]$AutoOrderConfig['itemId']
|
||||
if ([string]::IsNullOrWhiteSpace($itemId)) { $itemId = 'dmwmo3' }
|
||||
|
||||
$windowTitleHint = [string]$AutoOrderConfig['windowTitleHint']
|
||||
if ([string]::IsNullOrWhiteSpace($windowTitleHint)) { $windowTitleHint = "YLO'S Kitchen" }
|
||||
|
||||
$initialDelayMs = [int]$AutoOrderConfig['initialDelayMs']
|
||||
if ($initialDelayMs -le 0) { $initialDelayMs = 2500 }
|
||||
|
||||
$stepDelayMs = [int]$AutoOrderConfig['stepDelayMs']
|
||||
if ($stepDelayMs -le 0) { $stepDelayMs = 120 }
|
||||
|
||||
$toggleKeySetting = [string]$AutoOrderConfig['optionToggleKey']
|
||||
if ([string]::IsNullOrWhiteSpace($toggleKeySetting)) { $toggleKeySetting = 'SPACE' }
|
||||
$toggleKey = if ($toggleKeySetting.ToUpperInvariant() -eq 'ENTER') { '{ENTER}' } else { ' ' }
|
||||
|
||||
$calibrationOnly = [bool]$AutoOrderConfig['calibrationOnly']
|
||||
$calibrationTabs = [int]$AutoOrderConfig['calibrationTabs']
|
||||
if ($calibrationTabs -lt 0) { $calibrationTabs = 0 }
|
||||
|
||||
$tabsToOption1 = [int]$AutoOrderConfig['tabsToOption1']
|
||||
if ($tabsToOption1 -lt 0) { $tabsToOption1 = 3 }
|
||||
|
||||
$tabsBetweenOptions = [int]$AutoOrderConfig['tabsBetweenOptions']
|
||||
if ($tabsBetweenOptions -lt 0) { $tabsBetweenOptions = 2 }
|
||||
|
||||
$tabsToAddButton = [int]$AutoOrderConfig['tabsToAddButton']
|
||||
if ($tabsToAddButton -lt 0) { $tabsToAddButton = 4 }
|
||||
|
||||
$openCartPopup = [bool]$AutoOrderConfig['openCartPopupAfterAdd']
|
||||
$refreshBeforeCart = [bool]$AutoOrderConfig['refreshBeforeCart']
|
||||
$postRefreshDelayMs = [int]$AutoOrderConfig['postRefreshDelayMs']
|
||||
if ($postRefreshDelayMs -le 0) { $postRefreshDelayMs = 2500 }
|
||||
$tabsToCartButton = [int]$AutoOrderConfig['tabsToCartButton']
|
||||
if ($tabsToCartButton -le 0) { $tabsToCartButton = 5 }
|
||||
$tabsToConfirmButton = [int]$AutoOrderConfig['tabsToConfirmButton']
|
||||
if ($tabsToConfirmButton -le 0) { $tabsToConfirmButton = 3 }
|
||||
|
||||
$activationTimeoutMs = [int]$AutoOrderConfig['activationTimeoutMs']
|
||||
if ($activationTimeoutMs -le 0) { $activationTimeoutMs = 10000 }
|
||||
|
||||
$itemUrl = ($baseUrl.TrimEnd('/') + '/item/' + $itemId)
|
||||
|
||||
try {
|
||||
Add-Type -AssemblyName System.Windows.Forms -ErrorAction SilentlyContinue | Out-Null
|
||||
|
||||
Start-Process $itemUrl
|
||||
Write-Log -Level Info -Message "Opened item modal URL for auto-order: $itemUrl" -Feature $FeatureName
|
||||
Start-Sleep -Milliseconds $initialDelayMs
|
||||
|
||||
$shell = New-Object -ComObject WScript.Shell
|
||||
$hostHint = $null
|
||||
try { $hostHint = ([uri]$baseUrl).Host } catch {}
|
||||
|
||||
$activated = Invoke-AppActivateBestEffort -Shell $shell -TitleCandidates @(
|
||||
'Bestel online bij YLO''S Kitchen Pittem',
|
||||
'Bestel online bij YLO',
|
||||
'Bestel online bij',
|
||||
$windowTitleHint,
|
||||
($windowTitleHint -replace "'", ''),
|
||||
$hostHint,
|
||||
'ylos-kitchen',
|
||||
'unipage'
|
||||
) -TimeoutMs $activationTimeoutMs -RetryDelayMs 300
|
||||
|
||||
if (-not $activated) {
|
||||
Write-Log -Level Warn -Message "Could not foreground browser window (title hint '$windowTitleHint'). Skipping key automation to avoid acting on the wrong window." -Feature $FeatureName
|
||||
return $false
|
||||
}
|
||||
|
||||
if ($calibrationOnly) {
|
||||
for ($i = 0; $i -lt $calibrationTabs; $i++) {
|
||||
$shell.SendKeys('{TAB}')
|
||||
Start-Sleep -Milliseconds $stepDelayMs
|
||||
}
|
||||
|
||||
Write-Log -Level Info -Message ("Calibration mode completed: sent {0} TAB keys and stopped." -f $calibrationTabs) -Feature $FeatureName
|
||||
return $true
|
||||
}
|
||||
|
||||
# Modal flow keyboard navigation (best-effort; tab indexes are configurable).
|
||||
for ($i = 0; $i -lt $tabsToOption1; $i++) {
|
||||
$shell.SendKeys('{TAB}')
|
||||
Start-Sleep -Milliseconds $stepDelayMs
|
||||
}
|
||||
$shell.SendKeys($toggleKey)
|
||||
Start-Sleep -Milliseconds $stepDelayMs
|
||||
|
||||
for ($i = 0; $i -lt $tabsBetweenOptions; $i++) {
|
||||
$shell.SendKeys('{TAB}')
|
||||
Start-Sleep -Milliseconds $stepDelayMs
|
||||
}
|
||||
$shell.SendKeys($toggleKey)
|
||||
Start-Sleep -Milliseconds $stepDelayMs
|
||||
|
||||
for ($i = 0; $i -lt $tabsToAddButton; $i++) {
|
||||
$shell.SendKeys('{TAB}')
|
||||
Start-Sleep -Milliseconds $stepDelayMs
|
||||
}
|
||||
$shell.SendKeys('{ENTER}')
|
||||
Start-Sleep -Milliseconds 350
|
||||
|
||||
if ($openCartPopup) {
|
||||
if ($refreshBeforeCart) {
|
||||
$shell.SendKeys('{F5}')
|
||||
Write-Log -Level Info -Message 'Refreshing page to reset focus before tabbing to mini-cart.' -Feature $FeatureName
|
||||
Start-Sleep -Milliseconds $postRefreshDelayMs
|
||||
|
||||
$activated = Invoke-AppActivateBestEffort -Shell $shell -TitleCandidates @(
|
||||
'Bestel online bij YLO''S Kitchen Pittem',
|
||||
'Bestel online bij YLO',
|
||||
'Bestel online bij',
|
||||
$windowTitleHint,
|
||||
($windowTitleHint -replace "'", ''),
|
||||
$hostHint,
|
||||
'ylos-kitchen',
|
||||
'unipage'
|
||||
) -TimeoutMs $activationTimeoutMs -RetryDelayMs 300
|
||||
|
||||
if (-not $activated) {
|
||||
Write-Log -Level Warn -Message 'Could not re-foreground browser after refresh. Skipping cart popup.' -Feature $FeatureName
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0; $i -lt $tabsToCartButton; $i++) {
|
||||
$shell.SendKeys('{TAB}')
|
||||
Start-Sleep -Milliseconds $stepDelayMs
|
||||
}
|
||||
$shell.SendKeys('{ENTER}')
|
||||
Start-Sleep -Milliseconds $stepDelayMs
|
||||
|
||||
for ($i = 0; $i -lt $tabsToConfirmButton; $i++) {
|
||||
$shell.SendKeys('{TAB}')
|
||||
Start-Sleep -Milliseconds $stepDelayMs
|
||||
}
|
||||
$shell.SendKeys('{ENTER}')
|
||||
}
|
||||
|
||||
Write-Log -Level Info -Message 'Auto-order flow executed up to add-to-cart and cart popup open (best-effort).' -Feature $FeatureName
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
Write-Log -Level Error -Message "Auto-order flow failed: $_" -Feature $FeatureName
|
||||
return $false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user