Add Toast modifier extraction via Playwright
When analyzing Toast menu pages, items with modifiers now have their modifier groups extracted by clicking each item in a headless browser and intercepting the GraphQL MenuItemDetails responses. Extracted modifiers include group name, required/optional flag, min/max selections, and option names with prices. Items sharing the same itemGroupGuid inherit modifiers from successfully mapped siblings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
30dd0997b9
commit
aca3ba18a1
1 changed files with 83 additions and 1 deletions
|
|
@ -1034,6 +1034,9 @@
|
|||
<cfset itemStruct["name"] = trim(item.name)>
|
||||
<cfset itemStruct["category"] = groupName>
|
||||
<cfset itemStruct["modifiers"] = arrayNew(1)>
|
||||
<cfset itemStruct["hasModifiers"] = structKeyExists(item, "hasModifiers") AND item.hasModifiers EQ true>
|
||||
<cfset itemStruct["guid"] = structKeyExists(item, "guid") ? item.guid : "">
|
||||
<cfset itemStruct["itemGroupGuid"] = structKeyExists(item, "itemGroupGuid") ? item.itemGroupGuid : "">
|
||||
<cfset itemStruct["description"] = "">
|
||||
<cfif structKeyExists(item, "description") AND NOT isNull(item.description)>
|
||||
<cfset itemStruct["description"] = trim(toString(item.description))>
|
||||
|
|
@ -1101,6 +1104,9 @@
|
|||
<cfset itemStruct["name"] = trim(subItem.name)>
|
||||
<cfset itemStruct["category"] = subName>
|
||||
<cfset itemStruct["modifiers"] = arrayNew(1)>
|
||||
<cfset itemStruct["hasModifiers"] = structKeyExists(subItem, "hasModifiers") AND subItem.hasModifiers EQ true>
|
||||
<cfset itemStruct["guid"] = structKeyExists(subItem, "guid") ? subItem.guid : "">
|
||||
<cfset itemStruct["itemGroupGuid"] = structKeyExists(subItem, "itemGroupGuid") ? subItem.itemGroupGuid : "">
|
||||
<cfset itemStruct["description"] = "">
|
||||
<cfif structKeyExists(subItem, "description") AND NOT isNull(subItem.description)>
|
||||
<cfset itemStruct["description"] = trim(toString(subItem.description))>
|
||||
|
|
@ -1184,13 +1190,89 @@
|
|||
|
||||
<cfset arrayAppend(response.steps, "Extracted " & arrayLen(toastItems) & " items from " & arrayLen(toastCategories) & " categories via __OO_STATE__")>
|
||||
|
||||
<!--- Extract Toast modifiers via Playwright if items have modifiers --->
|
||||
<cfset toastModifiers = arrayNew(1)>
|
||||
<cfset modifierItemCount = 0>
|
||||
<cfloop array="#toastItems#" index="ti">
|
||||
<cfif structKeyExists(ti, "hasModifiers") AND ti.hasModifiers>
|
||||
<cfset modifierItemCount++>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
||||
<cfif modifierItemCount GT 0>
|
||||
<cfset arrayAppend(response.steps, modifierItemCount & " items have modifiers - extracting via Playwright")>
|
||||
<cftry>
|
||||
<!--- Determine Toast URL for Playwright --->
|
||||
<cfset toastUrl = "">
|
||||
<cfif isDefined("targetUrl") AND reFindNoCase("order\.toasttab\.com", targetUrl)>
|
||||
<!--- URL mode: use original URL --->
|
||||
<cfset toastUrl = targetUrl>
|
||||
<cfelse>
|
||||
<!--- Saved HTML mode: extract slug from HTML --->
|
||||
<!--- Try __APOLLO_STATE__ shortUrl first --->
|
||||
<cfset slugMatch = reMatchNoCase('"shortUrl"\s*:\s*"([^"]+)"', pageHtml)>
|
||||
<cfif arrayLen(slugMatch)>
|
||||
<cfset slug = reReplaceNoCase(slugMatch[1], '.*"shortUrl"\s*:\s*"([^"]+)".*', '\1')>
|
||||
<cfset toastUrl = "https://order.toasttab.com/online/" & slug>
|
||||
</cfif>
|
||||
<!--- Try gift card URL pattern --->
|
||||
<cfif NOT len(toastUrl)>
|
||||
<cfset giftMatch = reMatchNoCase('toasttab\.com/([a-zA-Z0-9_-]+)/giftcards', pageHtml)>
|
||||
<cfif arrayLen(giftMatch)>
|
||||
<cfset slug = reReplaceNoCase(giftMatch[1], '.*toasttab\.com/([a-zA-Z0-9_-]+)/giftcards.*', '\1')>
|
||||
<cfset toastUrl = "https://order.toasttab.com/online/" & slug>
|
||||
</cfif>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
<cfif len(toastUrl)>
|
||||
<cfset arrayAppend(response.steps, "Fetching modifiers from: " & toastUrl)>
|
||||
<cfset modOutput = "">
|
||||
<cfexecute name="/opt/playwright/run-toast-modifiers.sh" arguments="'#toastUrl#'" timeout="180" variable="modOutput" />
|
||||
|
||||
<cfif len(trim(modOutput))>
|
||||
<cfset modResult = deserializeJSON(modOutput)>
|
||||
|
||||
<!--- Extract modifiers --->
|
||||
<cfif structKeyExists(modResult, "modifiers") AND isArray(modResult.modifiers)>
|
||||
<cfset toastModifiers = modResult.modifiers>
|
||||
<cfset arrayAppend(response.steps, "Extracted " & arrayLen(toastModifiers) & " unique modifier groups")>
|
||||
</cfif>
|
||||
|
||||
<!--- Map modifiers to items --->
|
||||
<cfif structKeyExists(modResult, "itemModifierMap") AND isStruct(modResult.itemModifierMap)>
|
||||
<cfset modMap = modResult.itemModifierMap>
|
||||
<cfloop from="1" to="#arrayLen(toastItems)#" index="mi">
|
||||
<cfif structKeyExists(modMap, toastItems[mi].name)>
|
||||
<cfset toastItems[mi]["modifiers"] = modMap[toastItems[mi].name]>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
<cfset arrayAppend(response.steps, "Mapped modifiers to " & structCount(modMap) & " items")>
|
||||
</cfif>
|
||||
|
||||
<!--- Log stats --->
|
||||
<cfif structKeyExists(modResult, "stats") AND isStruct(modResult.stats)>
|
||||
<cfset arrayAppend(response.steps, "Modifier stats: " & serializeJSON(modResult.stats))>
|
||||
</cfif>
|
||||
<cfelse>
|
||||
<cfset arrayAppend(response.steps, "Playwright modifier script returned empty output")>
|
||||
</cfif>
|
||||
<cfelse>
|
||||
<cfset arrayAppend(response.steps, "Could not determine Toast URL for modifier extraction")>
|
||||
</cfif>
|
||||
<cfcatch>
|
||||
<cfset arrayAppend(response.steps, "Modifier extraction failed: " & cfcatch.message & " - continuing without modifiers")>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
</cfif>
|
||||
|
||||
<!--- Build and return response directly - skip Claude --->
|
||||
<cfif arrayLen(toastItems) GT 0>
|
||||
<cfset menuData = structNew()>
|
||||
<cfset menuData["business"] = toastBusiness>
|
||||
<cfset menuData["categories"] = toastCategories>
|
||||
<cfset menuData["items"] = toastItems>
|
||||
<cfset menuData["modifiers"] = arrayNew(1)>
|
||||
<cfset menuData["modifiers"] = toastModifiers>
|
||||
<cfset menuData["imageUrls"] = arrayNew(1)>
|
||||
<cfset menuData["imageMappings"] = imageMappings>
|
||||
<cfset menuData["headerCandidateIndices"] = arrayNew(1)>
|
||||
|
|
|
|||
Reference in a new issue