Saturday, December 14, 2013

Ruby code to check WorldMark resort availability.


Introduction:
I just recently got introduced to ruby and how better to practice some ruby code than to use it to solve a real world problem. So what is this real world problem you talk about.

I have a timeshare with Wyndham Resorts and these folks have 136 resorts all over the world. I am generally looking for 1 or 2 nights stay and mainly in Northern California and Nevada.
Also I am generally looking for a Friday or Saturday night stay. Ok so whats the problem... the problem is there is no telling when these dates will become available as people are constantly booking and cancelling 24 X 7. Hence what I would like is a program that would be able to log into worldmark and check specific dates and inform me if available or not.

I am breaking this little project up into 4 parts:

1. Login.
2. Check Availability.
3. Email me to inform availability.
4. Setup cron job to run program every hour.




# 1. Login Code:
#
# This ruby function does the log-in for worldmark.
# Its main library dependency is Mechanize (i.e. see
http://rubygems.org/gems/mechanize )
# 
# Author::    Peter Phelan  (mailto:pphelan69@gmail.com)
# Copyright:: Copyright (c) 2013 NetEire, LLC
# License::   Distributes under the same terms as Ruby
# 


require 'rubygems'
require 'mechanize'
require 'open-uri'


$agent = Mechanize.new


def loginWorldMark(user,password)
    $agent.get("https://www.worldmarktheclub.com/")
    $agent.page.forms[0]["number"] = user
    $agent.page.forms[0]["password"] = password
    $agent.page.forms[0].submit

end


# **************************************************



# 2. CheckAvailability code:
#
# This ruby function checks availability of a specific resort between certain 
# dates.
# Its main library dependency is Mechanize (i.e. see 
# http://rubygems.org/gems/mechanize )
# 
# Author::    Peter Phelan  (mailto:pphelan69@gmail.com)
# Copyright:: Copyright (c) 2013 NetEire, LLC
# License::   Distributes under the same terms as Ruby
# 

def checkAvailability(arrival,departure,destination)
    
    # Click the vacation planning link.
    link1 = $agent.click($agent.page.link_with(:text => /Vacation Planning/))
    
    # Check Availability form
    link1.forms[0].radiobutton_with(:value => /standard/).check
    link1.forms[0]["arrivalDateDisplay"]   = arrival
    link1.forms[0]["departureDateDisplay"] = departure
    link1.forms[0].field_with(:name => "resortId").option_with(:value => getLocationNo(destination)).click
    link1.forms[0].submit
    
    
    available = false
    if $agent.page.body.include?('/images/Book_It.gif') then
        puts destination + " is available from: " + arrival + " to: " + departure
        available = true
    elsif $agent.page.body.include?('We found no results for your query') then
        puts destination + " is not available from: " + arrival + " to: " + departure
    elsif $agent.page.body.include?('The number of nights requested exceeds 30 nights') then
        puts "The number of nights requested exceeds 30 nights."
    else
        puts "Error: You might have passed in invalid parameters:\n"
        puts "arrival: "     + arrival          + "\n"
        puts "departure: "   + departure   + "\n"
        puts "destination: " + destination + "\n"
        
    end
    
    return available
    
end




def getLocationNo(destination)
    locations = Hash.new
    
    locations = {
        "AZ-Bison Ranch" => "72",
        "AZ-Phoenix" => "68479",
        "AZ-Pinetop" => "96",
        "AK-Alyeska Hotel" => "225",
        "AZ-Rancho Vistoso" => "120",
        "CA-Anaheim" => "66778",
        "CA-Anaheim - Dolphins Cove" => "92",
        "CA-Angels Camp" => "70",
        "CA-Bass Lake" => "73",
        "CA-Big Bear" => "76",
        "CA-Clear Lake" => "87",
        "CA-Indio" => "125",
        "CA-Marina Dunes" => "88",
        "CA-Oceanside" => "126",
        "CA-Palm Springs" => "104",
        "CA-Pismo Beach" => "95",
        "CA-San Diego-Balboa Park" => "5072",
        "CA-San Diego-Inn at the Park" => "68801",
        "CA-San Diego-Mission Valley" => "61078",
        "CA-San Francisco" => "252",
        "CA-Solvang" => "2372",
        "CA-Windsor" => "107",
        "CAN-Canmore-Banff" => "56878",
        "CAN-Vancouver - The Canadian" => "103",
        "CAN-Victoria" => "109",
        "CAN-Whistler - Sundance" => "99",
        "CAN-Whistler-Cascade Lodge" => "85",
        "CO-Estes Park" => "251",
        "CO-Granby" => "68703",
        "CO-Steamboat Springs" => "101",
        "CO-Wyndham Durango" => "68179",
        "CO-Wyndham Pagosa" => "132",
        "FL- Daytona Beach - Ocean Walk" => "254",
        "FL-Orlando - Kingstown Reef" => "83",
        "FL-Orlando - Reunion" => "68499",
        "FL-Wyndham Palm-Aire" => "211",
        "FL-Wyndham Panama City" => "68459",
        "FL-Wyndham Sea Gardens" => "68000",
        "HI-Fairway Villa-Exchange" => "143",
        "HI-Kapaa, Kauai" => "75",
        "HI-Kihei, Maui" => "77",
        "HI-Kona, Big Island" => "78",
        "HI-Royal Kuhio-Exchange" => "142",
        "HI-Sea Village Exchange" => "68439",
        "HI-Valley Isle, Maui" => "105",
        "HI-Wyndham Bali Hai Villas" => "67679",
        "HI-Wyndham Kona Hawaiian" => "63178",
        "HI-Wyndham Royal Garden" => "68019",
        "ID-Arrow Point" => "71",
        "ID-Elkhorn Village-Exchange" => "2972",
        "ID-McCall" => "84",
        "IL-Galena" => "80",
        "LA-New Orleans - Avenue Plaza" => "1771",
        "MA-Wyndham Bentley Brook" => "68003",
        "MD-Wyndham National Harbor" => "68359",
        "MEX-Coral Baja" => "91",
        "MEX-La Paloma" => "108",
        "MEX-Mazatlan Exchange" => "133",
        "MEX-Vallarta Torre-Exchange" => "134",
        "MO-Branson" => "82",
        "MO-Lake of the Ozarks" => "90",
        "MT-West Yellowstone" => "61978",
        "NJ-Wyndham Skyline Tower" => "1773",
        "NM-Red River" => "58678",
        "NM-Santa Fe" => "66478",
        "NM-Taos" => "61678",
        "NV-Las Vegas Boulevard" => "127",
        "NV-Las Vegas Spencer Street" => "128",
        "NV-Las Vegas Tropicana Ave" => "59278",
        "NV-Reno" => "94",
        "NV-South Shore" => "170",
        "NV-Tahoe I, II, and III" => "214",
        "OK-Grand Lake" => "81",
        "OR-Bend-Seventh Mountain" => "68781",
        "OR-Depoe Bay" => "98",
        "OR-Eagle Crest" => "160",
        "OR-Gleneden" => "121",
        "OR-Running Y" => "93",
        "OR-Schooner Landing" => "122",
        "OR-Seaside" => "241",
        "SC-Wyndham Ocean Boulevard" => "224",
        "SC-Wyndham Ocean Ridge" => "68004",
        "SP-Ballarat" => "219",
        "SP-Cairns" => "218",
        "SP-Coffs Harbour Terraces" => "216",
        "SP-Coffs Harbour Treetops" => "68119",
        "SP-Crown Towers" => "64078",
        "SP-Denarau Island" => "102",
        "SP-Dunsborough" => "65578",
        "SP-Flynns Beach" => "221",
        "SP-Golden Beach" => "217",
        "SP-Kirra Beach" => "183",
        "SP-Lakes Entrance" => "2072",
        "SP-Pokolbin Hill Resort" => "182",
        "SP-Port Macquarie" => "220",
        "SP-Port Stephens" => "193",
        "SP-Ramada Phillip Island" => "68719",
        "SP-Ramada Port Douglas" => "68399",
        "SP-Rotorua, NZ" => "871",
        "SP-Seven Mile Beach, Hobart" => "2672",
        "SP-SurfAir Marcoola" => "67978",
        "SP-Surfers" => "68319",
        "SP-Sydney" => "3272",
        "SP-The Outram Perth" => "61378",
        "SP-Torquay" => "68419",
        "SP-Wanaka" => "67981",
        "TN-Wyndham Fairfield Glade" => "68002",
        "TN-Wyndham Nashville" => "223",
        "TN-Wyndham Smoky Mountains" => "130",
        "TX-New Braunfels" => "67378",
        "TX-Wyndham La Cascada" => "68001",
        "UT-Bear Lake" => "74",
        "UT-Midway" => "4472",
        "UT-St. George" => "110",
        "UT-Wolf Creek" => "271",
        "VA-Wyndham Kingsgate" => "131",
        "VI-St. Thomas" => "63478",
        "WA-Birch Bay" => "100",
        "WA-Chelan - Lake House" => "68739",
        "WA-Deer Harbor" => "3572",
        "WA-Discovery Bay" => "123",
        "WA-Lake Chelan Shores" => "79",
        "WA-Leavenworth" => "89",
        "WA-Long Beach" => "67085",
        "WA-Mariner Village" => "86",
        "WA-Seattle - The Camlin" => "124",
        "WA-Surfside Inn" => "106"
    }
    
    
    return locations[destination]
    

end



# Test code:
#  loginWorldMark("00210119349","mypassword")
checkAvailability("1/15/2014","1/16/2014","NV-South Shore")