ahertel / Amazon-Fresh-Whole-Foods-delivery-slot-finder

A Mac tool that finds available delivery slots for Amazon's Whole Foods delivery and Amazon Fresh services
MIT License
1.03k stars 171 forks source link

[Region Expansion] - UK - Code contribution #17

Open mannix515 opened 4 years ago

mannix515 commented 4 years ago

Hey there, we were chatting on reddit about this but wanted to add my changes here.

Screenshot of the slots page:

Reserve a Time Slot - Amazon co uk Checkout 2020-04-05 19-43-33

For no slots logic we have to check for three texts as it splits it out into morning. afternoon and evening blurbs and if all three are present then we know there's no slots. Otherwise, and as the screenshot shows, checking for lowercase "am" or "pm" works for the slot found logic - there's no need to check for the "slot_page_keyword" var as this is always present on the page even when there are no slots found.

My git is rusty, if I remember how to create a PR for my changes I'll put them in, otherwise find them here:

-- Source: https://www.cubemg.com/how-to-extract-information-from-a-website-using-applescript/
to clickClassName(theClassName, elementnum, tab_num, window_id)

    tell application "Safari"

        -- display dialog (text of last tab of window id amzn_win_id) as string
        -- display dialog (text of document 1) as string
        do JavaScript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();" in tab tab_num of window id window_id

    end tell

end clickClassName

-- variable definitions
set found_slot to false
set oos_keyword to "We're sorry we are unable to fulfill your entire order"
set oos_msg to "click 'continue' on out of stock page before closing this dialog box"
set unknown_page_msg to "Unknown amazon page was loaded. try to manually navigate back to the 'Schedule your order page', and then run the program again"
set slot_site_url to "https://www.amazon.co.uk/gp/buy/shipoptionselect/handlers/display.html?hasWorkingJavascript=1"
set slot_page_keyword to "Schedule your order"
set no_slot_keyword_m to "No morning delivery windows"
set no_slot_keyword_a to "No afternoon delivery windows"
set no_slot_keyword_e to "No evening delivery windows"
set is_first_run to true
set auto_ignore_oos to true

-- prompt whether to ignore oos or wait for user to review
display dialog "When items in your cart go out of stock, would you like the script to ignore it and keep looking for slots (recommended), or do you it to stop searching for slots until you manually review what went out of stock?" buttons {"Keep looking for slots", "Wait for me to review"} default button "Keep looking for slots"

if result = {button returned:"Keep looking for slots"} then
    set auto_ignore_oos to true -- redundant, but included for clarity
else if result = {button returned:"Wait for me to review"} then
    set auto_ignore_oos to false
end if

-- create new empty window, with one empty tab
tell application "Safari"
    make new document
    delay 0.5 -- wait for new window to open
    -- instead of creating a new tab in your current window, this creates a window and 'hides it by minimizing it. apple script doesn't allow you to move tabs around, all new tabs are created. an alternate solution would be to get the unique id of the tab and access it that way instead of putting the tab in a new window
    set amzn_win_id to id of front window
end tell

repeat while found_slot is false
    -- load the delivery slot page
    tell application "Safari"
        -- opens in a new tab every time instead of just using open url request, which would prompt "Are you sure you want to send a form again?" and prevent this from running neatly in the background
        tell window id amzn_win_id
            make new tab with properties {URL:slot_site_url}
            set current tab to last tab
        end tell
        if is_first_run is true then
            -- minimizes window on the first iteration so it can run quietly in background
            set miniaturized of window id amzn_win_id to true
            set is_first_run to false
        end if

        -- wait for the page to load
        delay 20

        -- get the text on the page
        set siteText to (text of last tab of window id amzn_win_id) as string
    end tell

    -- PROCESS PAGE CONTENTS:

    -- no delivery slots available
    if siteText contains no_slot_keyword_m and siteText contains no_slot_keyword_a and siteText contains no_slot_keyword_e then

        -- closes the tab since no slot was found
        tell application "Safari"
            close (last tab of window id amzn_win_id)
        end tell
        log "no slots found"

        -- delay so you don't spam Amazon's site
        delay 10
    else if siteText contains oos_keyword then
        -- landed on out of stock page

        if auto_ignore_oos then
            -- click continue button to dismiss out of stock warning
            clickClassName("a-button-text", 0, -1, amzn_win_id)

            log "Items out of stock were ignored"
            say "ignored oos item"
            -- delay to wait for the next page to load(it might be another oos page or the delivery slot page
            delay 20

            -- closes the tab so the tab can be reloaded and processed anew
            tell application "Safari"
                close (last tab of window id amzn_win_id)
            end tell
        else
            say "Item out of stock. See pop up"
            display dialog oos_msg
        end if

    else if siteText contains "am" or siteText contains "pm" then
        -- landed on delivery slot page and delivery slot selection drop down appears aka. slot found!
        display notification "Found delivery slot!" with title "Amazon" sound name "Sosumi"
        say "Success: Delivery slot found"
        set found_slot to true

        tell application "Safari"
            -- bring window to front
            set miniaturized of window id amzn_win_id to false
            -- wait for window to open
            delay 1
            -- maximize window so delivery slots are clearly visible
            -- this might be useful later on if I want to have it take a screenshot as proof of delivery slots found
            -- Credit for fill to screen: https://macosxautomation.com/applescript/firsttutorial/18.html
            tell application "System Events"
                tell application "Finder" to get the bounds of the window of the desktop
                tell application "Safari" to set the bounds of the front window to ¬
                    {0, 22, (3rd item of the result), (4th item of the result)}
            end tell
        end tell
    else
        -- encountered unknown page
        say "unknown page encountered. see pop up"
        display dialog unknown_page_msg
        -- correctly exit the loop and end the program
        set found_slot to true
    end if
end repeat

Thanks again for the initial work!

NathanSkene commented 4 years ago

Tried running this but didn't seem to work. It opened a general amazon UK window but didn't go to the fresh delivery page... then announced it had found a delivery. Would be great to get this working!

mannix515 commented 4 years ago

Tried running this but didn't seem to work. It opened a general amazon UK window but didn't go to the fresh delivery page... then announced it had found a delivery. Would be great to get this working!

Still working for me!

The delivery announcement sounds like a false positive to me due to only searching for "am" or "pm' strings which, on any other page could exist as part of other words, but on the delivery page only exist when a slot is found.

This might be better (untested):

else if siteText contains "00am" or siteText contains "00pm" then

In the above the times are incorporated too, and I think this should work as the slots are always hourly eg. 11:00am - 1:00pm and never (afaik) on the half or quarter-hour.

NathanSkene commented 4 years ago

Thanks for responding!

Am using safari and browsed to that page.

Is this (https://www.amazon.co.uk/gp/buy/shipoptionselect/handlers/display.html?hasWorkingJavascript=1) the delivery page for you?

I get this:

image

This seems to be the correct delivery webpage for me: https://www.amazon.co.uk/gp/buy/shipoptionselect/handlers/display.html?hasWorkingJavascript=1

mannix515 commented 4 years ago

No worries!

https://www.amazon.co.uk/gp/buy/shipoptionselect/handlers/display.html?hasWorkingJavascript=1 is correct - no idea why you're being redirected though - for me the script just refreshes in place once I've already browsed to that URL.

You can check the slot_site_url definition and it should match the URL of the delivery page where available slots are shown:

set slot_site_url to "https://www.amazon.co.uk/gp/buy/shipoptionselect/handlers/display.html?hasWorkingJavascript=1"