-
-
Save dat-vikash/2280dd53f37a6406fb73b719dc6f8cb2 to your computer and use it in GitHub Desktop.
""" | |
Helps make dad life easier by reserving times before pre-k. | |
Features: | |
- allow for filtering by time, day of week, number of player and course | |
- handles reservations and ensures no overbooking | |
- keeps track of default and state | |
Requires python3 and selenium: | |
+ https://sites.google.com/chromium.org/driver/ | |
+ https://selenium-python.readthedocs.io/ | |
""" | |
try: | |
from urllib.request import Request, urlopen # Python 3 | |
except ImportError: | |
from urllib2 import Request, urlopen # Python 2 | |
import json | |
import datetime | |
import time | |
import os | |
from selenium import webdriver | |
import pytz | |
COURSEIDS_MAP = { | |
"B": {"name":"Francis A. Byrne Golf Course", "id":"54f14d8a0c8ad60378b03e95"}, | |
"H": {"name":"Hendricks Field Golf Course", "id":"54f14d8a0c8ad60378b03e98"}, | |
"W": {"name":"Weequahic Park Golf Course", "id":"54f14d8b0c8ad60378b03e9c"} | |
} | |
local_tz = pytz.timezone('US/Eastern') | |
AUTO_RESERVATION=False | |
def login(driver): | |
""" | |
login to site | |
""" | |
driver.get(f"https://essex-group.book.teeitup.golf/login") | |
time.sleep(5) | |
username = driver.find_element("id","txtUsername") | |
password = driver.find_element("id","txtPassword") | |
# FILL in your county log in here | |
username.send_keys("") | |
password.send_keys("") | |
# Login and return driver with auth context | |
driver.find_element("xpath","//button[@data-testid='login-button']").click() | |
return driver | |
def reserve(tees): | |
""" | |
does the actual reservation | |
""" | |
reservations = load_reservations() | |
reservations_weekly_max = tees[0]['rounds_per_week'] | |
reservations_daily_max = tees[0]['rounds_per_day'] | |
# todo: get existing reservations | |
# existing_reservations = 0 | |
# | |
# reservations_weekly_max -= existing_reservations | |
# reservations_daily_max -= existing_reservations | |
drivers = [] | |
for tee in tees: | |
local_time = tee['teetime'].astimezone(local_tz) | |
course_name = list( | |
filter(None, | |
[COURSEIDS_MAP[c]['name'] if COURSEIDS_MAP[c]['id'] == tee['course'] else '' for c in COURSEIDS_MAP] | |
) | |
)[0] | |
if int(reservations['daily'].get(tee['date'], reservations_daily_max)) > 0 \ | |
and int(reservations['weekly'].get(local_time.strftime("%V"), reservations_weekly_max)) > 0 : # weekly check | |
print(f"Reserving Tee time for Date: {tee['date'] } Time: {local_time.strftime('%H:%M %p')} Course: {course_name} Available: {tee['playersAvail']} Fee: ${tee['fee']/100} Booking: {tee['num_player_booking']}") | |
# start driver and get auth context | |
driver = webdriver.Chrome() | |
driver = login(driver) | |
time.sleep(5) | |
drivers.append(driver) | |
# time to book it | |
driver.get(f"https://essex-group.book.teeitup.golf/?course={tee['course']}&date={tee['date']}") | |
t = tee['teetime'].strftime('%-H:%M %p') | |
time.sleep(5) | |
# find the tee time | |
button = driver.find_element(f"xpath",f"//p[@data-testid='teetimes-tile-time'][contains(., '{t}')]").find_element("xpath","./../..").find_element("xpath","//button[@data-testid='teetimes_book_now_button']") | |
button.click() | |
time.sleep(3) | |
# checkout | |
driver.find_element("xpath",f"//button[@data-testid='button-value-{tee['num_player_booking']}']").click() | |
driver.find_element("xpath","//span[contains(.,'Proceed to Checkout')]").click() | |
time.sleep(5) | |
# no turning back | |
driver.find_element("name","chb-nm").click() | |
# todo: actually checkout | |
# driver.find_element("xpath","//button[@data-testid='make-your-reservation-btn']").click() | |
# update reservations | |
reservations['daily'].update({tee['date']: reservations['daily'].get(tee['date'],reservations_daily_max) - 1 }) | |
reservations['weekly'].update({local_time.strftime("%V"): reservations['weekly'].get(local_time.strftime("%V"),reservations_weekly_max) - 1 }) | |
else: | |
print(f"Daily/Weekly Max Filled for Reserving Tee time for Date: {tee['date'] } Time: {local_time.strftime('%H:%M %p')} Course: {course_name} Available: {tee['playersAvail']} Fee: ${tee['fee']/100} Booking: {tee['num_player_booking']}") | |
time.sleep(5) | |
for d in drivers: | |
d.quit() | |
write_reservations(reservations) | |
def banner(): | |
banner = """ | |
'\ . . |>18>> | |
\ . ' . | | |
O>> . 'o | | |
\ . | | |
/\ . | | |
/ / .' | | |
jgs^^^^^^^`^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
""" | |
print(banner) | |
def ranger(teetimes): | |
for t in teetimes: | |
print("Date: " + t['date'] + " Time: " + t['teetime'].strftime('%H:%M')) | |
count = 0 | |
while count < 300: | |
if count % 30 : | |
os.system('say -v "Victoria" "TEE TIMES FOUND, HURRY UP"') | |
time.sleep(1) | |
count += 1 | |
def load_reservations(): | |
data = [] | |
if os.path.exists('reservations.json'): | |
f = open('reservations.json') | |
data = json.load(f) | |
f.close() | |
else: | |
data = {'weekly':{}, 'daily':{}} | |
return data | |
def write_reservations(payload): | |
if os.path.exists('reservations.json'): | |
pass | |
else: | |
print("reservations File created.") | |
with open('reservations.json', "w") as outfile: | |
outfile.write(json.dumps(payload)) | |
return | |
def load_defaults(): | |
data = None | |
# Opening JSON file | |
if os.path.exists('config.json'): | |
f = open('config.json') | |
data = json.load(f) | |
f.close() | |
return data | |
def write_defaults(payload): | |
if os.path.exists('config.json'): | |
pass | |
else: | |
print("Default File created.") | |
with open('config.json', "w") as outfile: | |
outfile.write(json.dumps(payload)) | |
return | |
def get_filters(): | |
# load defaults | |
defaults = load_defaults() | |
if defaults is None: | |
print("""" | |
##### Inital Setup: Fill out scorecard #### | |
""") | |
# get round details | |
starting_tee_time = int(input("Enter the earliest hour you can tee off in 24 hour time (ex: 7 for 7 am, 13 for 1 pm): ")) | |
ending_tee_time = int(input("Enter the latest hour you can tee off in 24 hour time (ex: 7 for 7 am, 13 for 1 pm): ")) | |
num_players = int(input("How many players to reserve?: ")) | |
auto_reserve = input("Should I auto reserve for you (y for yes, n for no)?: ") | |
# print out course | |
print("\n### Course's Available ###") | |
[print(key + " - " + COURSEIDS_MAP[key]['name']) for key in COURSEIDS_MAP.keys()] | |
print("A - ALL") | |
courses = input(f"Which course(s) to search?: ") or "A" | |
dow = input("""Which day(s) of the week: | |
1 = Monday | |
2 = Tuesday | |
3 = Wednesday | |
4 = Thursday | |
5 = Friday | |
6 = Saturday | |
7 = Sunday | |
A = ALL | |
Ex: 1,2 for mon/tues or 1 for mon only or A for all): """) or "A" | |
rounds_per_week = int(input("How many rounds to reserve per week? : ") or 1) | |
rounds_per_day = int(input("How many rounds to reserve per day? : ") or 1) | |
if dow == "A" or dow == "a": | |
dow = None | |
else: | |
dow = dow.split(",") | |
if courses == 'A': | |
courses = ",".join(list([f"{COURSEIDS_MAP[key]['id']}" for key in COURSEIDS_MAP.keys()])) | |
else: | |
courses = COURSEIDS_MAP[courses]['id'] | |
else: | |
# use defaults | |
print("Loading defaults") | |
starting_tee_time = defaults['starting_tee_time'] | |
ending_tee_time = defaults['ending_tee_time'] | |
courses = defaults['courses'] | |
dow = defaults['dow'] | |
num_players = defaults['num_players'] | |
rounds_per_week = defaults['rounds_per_week'] | |
rounds_per_day = defaults['rounds_per_day'] | |
auto_reserve = defaults['auto_reserve'] | |
if auto_reserve == 'y': | |
AUTO_RESERVATION = True | |
# Adjust for utc | |
starting_tee_time += 4 | |
ending_tee_time += 4 | |
# get date range for next couple days | |
base = datetime.datetime.today() | |
numdays=10 | |
date_list = [base + datetime.timedelta(days=x) for x in range(numdays)] | |
# figure out tee times | |
all_times = {} | |
for date in date_list: | |
#check filters | |
if dow is None or str(date.isoweekday()) in dow: | |
# get tee times | |
date_str = date.strftime('%Y-%m-%d') | |
print("Working on tee times for day: " + date_str) | |
req = Request(f"https://phx-api-be-east-1b.kenna.io/tee-times?date={date_str}&courseIds={courses}") | |
req.add_header('x-be-alias', 'essex-group') | |
content = urlopen(req).read() | |
info = json.loads(content) | |
tee_times = [] | |
for result in info: | |
tee_times += result['teetimes'] | |
newlist = sorted(tee_times, key=lambda d: datetime.datetime.strptime(d['teetime'], '%Y-%m-%dT%H:%M:%S.%fZ')) | |
all_times[date_str]=newlist | |
time.sleep(1) | |
# filter for acceptable times | |
final_tees = [] | |
for dayslot in all_times: | |
for timeslot in all_times[dayslot]: | |
hour = datetime.datetime.strptime(timeslot['teetime'], '%Y-%m-%dT%H:%M:%S.%fZ').hour | |
playerBookedCount = timeslot['bookedPlayers'] | |
playerAvailCount = timeslot['maxPlayers'] | |
if (hour >= starting_tee_time) \ | |
and (hour < ending_tee_time) \ | |
and playerAvailCount >= num_players: | |
final_tees.append({"date":dayslot, | |
"teetime": datetime.datetime.strptime(timeslot['teetime'], '%Y-%m-%dT%H:%M:%S.%fZ') - datetime.timedelta(hours=4), | |
"playersBooked": playerBookedCount, | |
"playersAvail": playerAvailCount, | |
"course":timeslot['courseId'], | |
"fee": timeslot['rates'][0]['greenFeeWalking'], | |
"num_player_booking":num_players, | |
"rounds_per_day":rounds_per_day, | |
"rounds_per_week":rounds_per_week}) | |
write_defaults({'starting_tee_time':starting_tee_time-4, 'ending_tee_time':ending_tee_time-4, 'courses':courses, 'dow':dow, 'num_players':num_players,"rounds_per_day":rounds_per_day, | |
"rounds_per_week":rounds_per_week, 'auto_reserve':auto_reserve}) | |
return final_tees | |
def runner(): | |
banner() | |
final_tees = get_filters() | |
if len(final_tees) > 0: | |
print("Times Available") | |
for idx,t in enumerate(final_tees): | |
local_time = t['teetime'].astimezone(local_tz) | |
course_name = list( | |
filter(None, | |
[COURSEIDS_MAP[c]['name'] if COURSEIDS_MAP[c]['id'] == t['course'] else '' for c in COURSEIDS_MAP] | |
) | |
)[0] | |
print(f"[{idx}] Date: {t['date'] } Time: {local_time.strftime('%H:%M %p')} Course: {course_name} Available: {t['playersAvail']} Fee: ${t['fee']/100}") | |
do_reserve = 'n' | |
if AUTO_RESERVATION is False: | |
do_reserve = input("Proceed with reservation? , y for yes, n for no: ", "n") | |
if AUTO_RESERVATION or do_reserve == "y": | |
reserve(final_tees) | |
if __name__ == "__main__": | |
runner() |
dat-vikash
commented
Aug 2, 2022
•
How do you pull the course ids?
COURSEIDS_MAP = {
"B": {"name":"Francis A. Byrne Golf Course", "id":"54f14d8a0c8ad60378b03e95"},
"H": {"name":"Hendricks Field Golf Course", "id":"54f14d8a0c8ad60378b03e98"},
"W": {"name":"Weequahic Park Golf Course", "id":"54f14d8b0c8ad60378b03e9c"}
If you’re searching for a reliable Beaumont truck accident attorney, look no further than Markarian Law Group. We understand the devastating impact a truck accident can have on your life and are dedicated to helping you recover the compensation you deserve. From investigating the cause of the accident to holding negligent parties accountable, our experienced legal team will stand by your side every step of the way. With a focus on client care and a proven track record of success, Markarian Law Group is your trusted partner in pursuing justice after a truck accident.
Discover the premier learning experience with Chicago Home Tutor, where personalized education meets exceptional results. At Chicago Home Tutor, students of all ages and abilities receive tailored tutoring designed to unlock their full potential. Whether your child needs support in math, reading, test preparation, or advanced studies, our dedicated team of expert educators creates customized strategies that foster confidence and academic success. With a commitment to excellence and a passion for empowering learners, Chicago Home Tutor stands as the trusted partner for families seeking unparalleled academic support in the heart of Chicago.
When plumbing emergencies strike, AYS Plumbing & Rooter is the go-to solution for Upland emergency plumbing. Offering fast, reliable service, their experienced team is available around the clock to handle everything from pipe bursts to sewer backups. With a focus on high-quality workmanship and customer satisfaction, AYS Plumbing & Rooter is committed to resolving your plumbing issues swiftly and efficiently. Don’t let a plumbing problem disrupt your life—visit their [website for trusted emergency plumbing services in Upland today!
For reliable Claremont emergency plumbing, AYS Plumbing & Rooter is the team you can depend on. From burst pipes to stubborn clogs, their 24/7 emergency services ensure that no plumbing issue is too big or too small to handle. With a focus on fast response times, professional expertise, and customer satisfaction, AYS Plumbing & Rooter provides solutions that restore your peace of mind. When every moment counts, trust the experts committed to getting your plumbing back on track quickly and efficiently.
At Oceanic Yacht Management, we take pride in offering top-tier Boca Raton Boat Detailing services that keep your yacht looking its best. Our skilled team uses advanced techniques and high-quality products to deliver impeccable results, ensuring your boat stays pristine year-round. Whether you're preparing for a special outing or simply maintaining the beauty of your vessel, our boat detailing services are designed to enhance both the appearance and longevity of your yacht. With our attention to detail and commitment to excellence, Oceanic Yacht Management is your trusted partner for all your boat care needs in Boca Raton.
Elevate your beauty with the finest filler treatments in Tampa at The Aesthetics Lounge and Spa. Renowned for delivering natural, rejuvenating results, this premier spa offers expert care tailored to your unique needs. Whether enhancing volume, smoothing lines, or defining your features, their skilled professionals use cutting-edge techniques to help you look and feel your best. Discover the perfect blend of artistry and science—visit The Aesthetics Lounge and Spa Tampa to begin your transformation today!
Discover the ultimate rejuvenation experience at The Laser Lounge Spa North Naples, your premier Naples med spa destination. Offering a wide range of advanced skincare treatments, this luxurious spa is dedicated to enhancing your natural beauty with personalized services that cater to your unique needs. Whether you're seeking a refreshing facial, body contouring, or laser treatments, the expert team at The Laser Lounge Spa ensures a safe, effective, and indulgent experience. Escape into a world of relaxation and transformation at this top-rated Naples med spa, where your satisfaction and wellness are always the priority. Visit us today and discover how we can help you look and feel your absolute best.
Revitalize your skin and restore its natural glow with Sarasota hydrating facials at The Laser Lounge Spa Sarasota. Designed to deeply nourish and rejuvenate, these facials are perfect for combating dryness and promoting a radiant complexion. Our expert aestheticians use premium skincare products and advanced techniques to deliver unparalleled hydration, leaving your skin feeling soft, smooth, and refreshed. Whether you're preparing for a special occasion or simply indulging in self-care, our hydrating facials offer a luxurious escape for your skin and soul. Experience the transformative power of hydration and book your appointment today!
Discover the rejuvenating power of Orlando chemical peels at The Aesthetics Lounge and Spa Orlando. Our expert team uses advanced techniques and top-quality products to provide customized chemical peel treatments that target skin imperfections, improve texture, and promote a youthful glow. Whether you're dealing with acne scars, fine lines, or sun damage, our treatments are designed to revitalize your skin, leaving you with a smoother, more radiant complexion. Visit us today and experience the transformative benefits of chemical peels in Orlando—your skin will thank you!
Looking for reliable and high-quality asphalt paving in San Jose? Look no further than Granite Northwest Grading & Paving! With years of experience, they offer exceptional paving solutions tailored to meet your specific needs. Whether you’re looking to improve the driveway of your home or upgrade a commercial parking lot, their expert team ensures top-notch service with lasting results. Committed to precision and professionalism, they use the best materials and cutting-edge techniques to deliver a smooth, durable surface that will stand the test of time. Visit here to explore their comprehensive paving services and get started today!
Looking for reliable and efficient junk removal services in San Luis Obispo? Look no further than Junk Removal in SLO! Our professional team is dedicated to making your space clutter-free by offering top-notch junk removal solutions tailored to your needs. Whether you’re clearing out an old garage, decluttering your home, or managing a commercial cleanup, we handle it all with ease. We pride ourselves on eco-friendly practices, ensuring that your unwanted items are disposed of responsibly. Trust us for fast, friendly, and affordable junk removal services in San Luis Obispo!
When a plumbing emergency strikes, turn to AYS Plumbing & Rooter for dependable and immediate assistance. Specializing in Upland emergency plumbing, they are your go-to experts for burst pipes, overflowing toilets, or unexpected leaks. Available 24/7, their skilled team is equipped with advanced tools and expertise to resolve issues quickly and efficiently, protecting your home from further damage. With a commitment to quality service and customer satisfaction, AYS Plumbing & Rooter ensures your plumbing woes are handled with care. Visit their website today to get the help you need when you need it most!
For reliable Upland emergency plumbing, turn to the trusted professionals at AYS Plumbing & Rooter. Whether it’s a burst pipe, a clogged drain, or a sudden leak, their expert team is available 24/7 to provide swift and effective solutions. Known for their prompt response and high-quality service, they work diligently to resolve emergencies and restore your plumbing with minimal disruption. Don’t let unexpected plumbing issues derail your day—visit their website now and get fast, dependable help from the experts you can count on!
When a plumbing emergency strikes, you need a fast and dependable solution. AYS Plumbing & Rooter is your trusted expert for Upland emergency plumbing, providing 24/7 service to handle burst pipes, clogged drains, leaks, and more. Our skilled plumbers respond quickly to minimize damage and restore your plumbing with precision and care. With a reputation for reliability and top-quality workmanship, we ensure your home or business is back to normal in no time. Don’t wait—call us now for immediate assistance!
When plumbing disasters strike, you need a team you can trust to respond fast. AYS Plumbing & Rooter specializes in Upland Emergency Plumbing, providing 24/7 rapid assistance for burst pipes, overflowing drains, water heater failures, and more. With skilled technicians, cutting-edge equipment, and a commitment to excellence, we ensure quick, effective solutions to keep your home or business running smoothly. Don’t let plumbing issues cause unnecessary stress—call AYS Plumbing & Rooter now for immediate, reliable emergency service!
If you're searching for expert contractors in Plymouth MA, look no further than Level 20 Construction. We specialize in high-quality residential and commercial construction, delivering exceptional craftsmanship, innovative solutions, and seamless project management. Whether you're renovating your home, expanding your business, or starting a custom build, our skilled team ensures precision and efficiency at every step. With a strong reputation for reliability and excellence, we bring your vision to life with superior results. Trust Level 20 Construction for all your building needs—visit our website to learn more!
When it comes to expert construction services, Level 20 Construction is a top choice among Plymouth MA general contractors. With a reputation for quality craftsmanship and attention to detail, they specialize in residential and commercial projects, delivering outstanding results tailored to your needs. Whether you're planning a home renovation, a new build, or a commercial upgrade, their skilled team ensures a seamless process from start to finish. Dedicated to excellence and customer satisfaction, Level 20 Construction transforms visions into reality with precision and care. Visit their website today to start your next project with trusted professionals!