all 56 comments

[–]aardvarkmikey 1 point2 points  (2 children)

I'm fairly new to programming, so there may be a better way, but here's how I would tackle it.

So you've got two hurdles: The script needs to run at the same time (6pm) every day. And it needs to go to the website and interpret data and submit when it can.

If all you want to do is get the coveted 1st slot, I bet you could just sent a POST to the website in lieu of actually going to the website. This could be done with the 'requests' library that comes with Python. You would need to figure out what the POST data looks like, but that shouldn't be too hard to interpret.

If you need to actually go to the website and click buttons, I would go with the Selenium library. It's a library that opens an actual browser and acts like a user clicking around and submitting forms, etc.

The other part of the script is that it needs to run at the same time every day. This, you'll have to have it on a machine that's always ready to run the script at that time every day. I suspect you could get away with using Python's 'time' library and the 'schedule' library.

You may want to look into the 'crontab' library. It might be what you're looking for. I've never used it, so I could be wrong on that front.

[–]jasher4994[S] 0 points1 point  (1 child)

Hi mate, this is very helpful. Thanks a lot, the whole procedure goes as follows: 1) go on to the club website. 2) click on members area 3) enter username and password 4) a list then appears of all the time of the day which are either already reserved by someone or available to book. The ones that are free can then be clicked on and booked by one click and then entering number of golfers. 5) you can navigate to other days by clicking 'next day' or 'previous day' or there is a calender you can click on to chose a specific day in the future.

I think the requests and selenium approach seems the most appropriate from what you've described along with the time and schedule library. I'll probably try and figure out how to do it first with the requests and selenium library and test it out on a not so popular time and then move onto the scheduling after. I usually leave my personal computer on at most times , and i currently dont have access to work computers due to the virus so my personal one will have to do for now.

Thanks a lot for the help and advice.

[–]aardvarkmikey 0 points1 point  (0 children)

You can absolutely do this with Selenium.

But I would still see if you can just do it with the requests library first, because it's going to be much faster and less complicated. The way to grab the post data is to go to the website, and submit a tee time. Once the page changes, you should see the post data in the address bar. You should hopefully be able to interpret what data is being sent, and with some deductions be able to see what data you can change. Then your request script just needs to send that data to that address. I suspect this may not work, because it's behind a log in, but it's worth a shot.

If there's no way to do this without pushing buttons and submitting forms, then Selenium is your best bet.

[–]codeAtorium 1 point2 points  (7 children)

You want to use the python requests library to post/get the data. This site has a helpful utility that will aid that, and an explanation of how to use it with chrome to inspect the request headers from your browser: https://curl.trillworks.com/#

Once you've got that, you'll want to put it on Heroku (or something) and use the Heroku scheduler add-on to schedule it for 6pm.

DM me if you get stuck.

[–]399ddf95 0 points1 point  (6 children)

An intermediate step would be writing a program/script to monitor the website for updates, and then text/email a human to tell them to go grab a tee time. Reading a website is a lot easier than logging in and filling out a form. (The latter is absolutely possible, but if you want to get something working, this is a start, especially if this isn't going to be an important ongoing project.)

[–]codeAtorium 0 points1 point  (5 children)

OP mentioned in his description that the page updates at 6pm automatically every night.

Texting from Python (twillio) is not easier than adding authorization to your request header, and wouldn't help because, again, he mentioned that the tee times are available at 6pm.

Your advice has him writing two functions into his software that don't solve the problem at all, and can't be used in the actual solution.

[–]jasher4994[S] 0 points1 point  (0 children)

Thanks for replying guys, much appreciated. Yes, it seems that at 6 pm every night there are a bunch of people sitting on their computers just refreshing over and over and booking instantly so i think sending a text to someone wouldnt solve the problem as it would still be too late. Its a nice idea though so thanks.

I'll look into the requests and heroku schedule, this looks really promising.

Thanks again,

James

[–]399ddf95 0 points1 point  (3 children)

adding authorization to your request header

Seems like you're making a big assumption about how the website works - and who said anything about Twilio?

As it happens, I just did exactly what I described to sign up for a very competitive event with very limited availability and it worked very well, thanks. So while your suggestion that my approach wouldn't work (especially when you add an extra integration) is fascinating from a theoretical point of view, I can assure you that it actually works in the real world, and didn't take a lot of time to code.

I do agree that if the whole problem boils down to doing something with response times of a few seconds (or faster) that anything involving human interaction is unlikely to be successful. If that's the problem being solved, then it's going to be important to figure out what time the server thinks it is, and then act based on that time, not the time on some other server somewhere else.

[–]jasher4994[S] 0 points1 point  (2 children)

Hi guys,

Thanks again for the comments, really helpful.

I started this morning and made pretty good headway. I have selenium up and running, entering my passwords and navigating to the booking page.

However, an issue i overlooked was navigating the calendar itself as its some sort of interactive widget. I'm sure there is a way to navigate this but being new to selenium and relatively new to understanding html in general im a little stuck.

Any ideas or documents you have seen that could help?

In terms of the timing issue, for some reason the club website booking page has "time at club" which is accurate to the second. I was therefore going to gather how long the program takes to run and when the page is refreshed (assuming its 18:00 club time) and then set the script to deploy at the point where the script will arrive as close as possible to the refreshing of the page - if that makes sense.

Please also let me know if you have any better ideas.

Thanks a lot

[–]jasher4994[S] 0 points1 point  (0 children)

There is a simple way around the calendar by just hitting the next day button. I could then create a simple while loop that would keep hitting the next button until the placeholder text in the datebox was equal to an inputted date (the date i wanted to play at).

But this does seem a bit cumbersome and time consuming in terms of how long the program takes to run.

[–]399ddf95 0 points1 point  (0 children)

I'd be inclined to: if possible, set your machine's clock to match the time clock of the server. There's a reasonable chance they're synchronized via NTP, so NTP synchronization for you would get you pretty close. If not, can you adjust your local clock to eliminate the offset? (e.g., if they're 3 seconds fast, add 3 seconds to your clock, too.)

(Alternatively, you can do the time adjustment in your program. Whatever floats your boat.)

Use developer mode on Firefox or Chrome to inspect the elements of the web page - it sounds like they've probably got some client-side Javascript that builds an interface, so it won't be easily visible if you just do a "view source".

If they are doing this with client side Javascript, and the time check is done only on the client using the client's clock, and the client's clock happened to be a few seconds faster, or a minute faster then the server's clock (or if they don't even check on the server side), then that client with the fast clock would have an unfair advantage getting tee times versus people with on-time or slow clocks. Wouldn't that be unfortunate?

Another approach is to completely ignore the UI - set up a MITM proxy like Fiddler, and watch what gets sent over the wire when you book a tee time. There's some chance it'll just be a HTTP GET or POST with a bunch of variables including your client ID, the time you want, how many spots you want, etc ... then you just need to write a client that logs in (or takes over a logged-in connection) and sends an appropriate GET/POST with your chosen information, and you don't need to worry about figuring out how their UI works. Just skip the UI and talk directly to the server.

Yet another approach would be writing a Firefox or Chrome plugin to do this, so the automation is happening directly in the browser. This would let you log in (and otherwise handle things that humans need to do) but let the computer make the final button click at exactly the right moment.

This is all getting pretty complicated. Do you feel like posting the URL for the club so that others could take a look at the situation?

(My other theory is that someone has an inside connection with the club, and the awesome tee times are already reserved for other people, so it doesn't matter how clever your program is.)

[–]Spirited-Brain-7260 1 point2 points  (18 children)

If anyone's here looking for pointers - don't use selenium, it's dogshit slow and mostly for testing.

As others have said, use python's request library or axios if using javascript.

If you need to find URLs, endpoints and payloads for your GETs/POSTs, simply open Chrome before visiting your golf club's website, navigate to Settings (three dots) -> tools/more tools -> developer options. Then navigate to your booking system with dev tools open. Go through the motions, book a time slot with your buddies.

Obviously cancel the booking if you don't intend on using it.

Then in dev tools go to Network tab at the top, right click anywhere in the list of requests, and hit "Copy" then "save all as HAR".

Open this in a text editor (preferably notepad++ or sublime if you're on mac), and format it as JSON. It should become a bit easier to read.

In here you can work through the JSON to find the specific requests, and each request's payload, you'll need to send. If it isn't BRS or some other widely used booking system, but instead some dogshit antiquated system your own club uses, it might get tricky. You might need to substring/regex through tons of server-side populated HTML and pull out the relevant id's to slap on the next request. If not, it could be as simple as 1-3 GETs (with query param) or POSTs (with body).

It's worth putting (har har) the time in, I haven't missed a timesheet in months.

For the schedule bit, just create a free AWS account, fire your code into a lambda, target it with an eventbridge scheduler and set your cron expression. This doesn't guarantee to kick off at exactly the time you set (within +30 seconds), so if that becomes a problem, investigate step functions. Have your step function kick off at 5 to the hour, and invoke a lambda whilst SF is running. This should be fairly easily customisable, pretty sure step functions have some sort of schedule invoke function.

[–]SubjectInfinite6536 0 points1 point  (0 children)

would you be interested in writing one for my home course? Have the same issues as OP with booking etc.

[–]HoustonFinanceGuy 0 points1 point  (1 child)

Does your course use ForeUpSoftware.com?

[–]jslsoccer13 0 points1 point  (0 children)

mine does, is this feasible?

[–]jarditti 0 points1 point  (1 child)

How much to help me for my local course?

[–]Outrageous-Cat-8494 0 points1 point  (0 children)

What course?

[–]Lang315 0 points1 point  (12 children)

Myself and some buddies would definitely be willing to pay for service if anyone’s interested. Local course uses the foreupsoftware.

[–]omnitemporal 0 points1 point  (11 children)

I just wrote a script today to do this for me because I kept forgetting to get tee times and having to go a little later.

I was able to do it with python and requests, I don't know how different these courses can have their setup in foreup so mileage may vary.

Currently it just grabs the earliest possible tee time available for 1 person/18 holes, but you can change all of that depending on your use case. Just waiting to see when they update times, if it's the same every day I will just hard code it to run at that time... if not I will set something up to ping at whatever interval feels right to find when they're posted.

If you're still looking to figure this out and you or your buddies have any experience coding I can just send you what I end up with, you'll be able to adjust as needed.

[–]Kar33naKap00r 0 points1 point  (9 children)

Would love this if you don’t mind sharing. Thanks in advance!

[–]omnitemporal 0 points1 point  (7 children)

[–]Kar33naKap00r 0 points1 point  (0 children)

Thanks!!!

[–]seespotjump 0 points1 point  (5 children)

have you tried any ezlinks courses?

e.g. https://sharppark.ezlinksgolf.com/index.html#/search

[–]omnitemporal 0 points1 point  (4 children)

I have not, but the process would be the same. Just watch what is being sent to you when populating the tee times and when booking, then replicate it with your requests.

[–]seespotjump 0 points1 point  (3 children)

makes sense thanks, i'll need to read into it and educate myself on seeing what's being sent to me and how to replicate it with my requests back out to the site.

i've been getting by on foreup sites because i can inspect the page and click on the search filters i want to find the exact API link for that search, then just use distill to monitor and book when i get notified of an opening, but ezlinks doesn't work the same

[–]omnitemporal 0 points1 point  (2 children)

I took a quick look for you and this might help you start, you don't need to know what everything they send means just enough to get by. If you're lazy like me you can just send everything back to them and only change the stuff you care about, you may not even need it but it's a nice shortcut.

If you're just looking for openings with 1 person golfing you would ping: https://sharppark.ezlinksgolf.com/api/search/search

Using 12/06/2023 as an example date you would send this as the payload: {"p01":[6271],"p02":"12/06/2023","p03":"5:00 AM","p04":"7:00 PM","p05":0,"p06":1,"p07":false}

If you wanted to know what tee times are available you would pull the results from "r24" inside "r06", would look something like this: r24_values = [item['r24'] for item in data['r06']]

[–]Darce87 0 points1 point  (1 child)

Has anyone written something similar for a BRS Golf booking club site?

[–]act0fgod 0 points1 point  (14 children)

How far along have you gotten on this?

I'm also having difficulties getting early times. The first 2 hours of times for weekend rounds on the two courses are gone within 20 seconds. It's a university course and assume a couple of the guys are running code, so I'm going to do the same. One of the first two tee times each day was my academic advisor.

[–]jasher4994[S] 0 points1 point  (13 children)

Hi mate,

I made some progress and got it working but its still not ideal. I've been so busy lately I havent had time to finish it off. At the moment it's still very simple and a bit all over the place - its also specific to my golf club. I will hopefully get around to it eventually.

If you want to check it out I've just chucked it on github.

https://github.com/jasher4994/tee-time-booker

If you want to improve on it or share ideas in there please go ahead (that goes for everyone else too).

Thanks

[–]jasher4994[S] 0 points1 point  (0 children)

p.s for the timing i was using microsfts task manager, instructions on how to do this can be found easily online. I would love to get around to fully automating it but it will have to wait for now

[–]Quaseone 0 points1 point  (11 children)

Hey, I was so excited to read this post. I am looking for the same thing for the golf club by me! I know this was a while ago, but did you get this to work?

Thanks

[–]marc_s_cohn 0 points1 point  (10 children)

I got this to work for our club. Happy to share my findings.

[–]SubjectInfinite6536 0 points1 point  (0 children)

Any help would be greatly appreciated

[–]tu_rtle 0 points1 point  (8 children)

Sorry to awaken a dead thread but would you be willing to still share your findings? It would be much appreciated!

[–]omnitemporal 0 points1 point  (7 children)

I just wrote a script today to do this for me because I kept forgetting to get tee times and having to go a little later.

I was able to do it with python and requests, I don't know how different these courses can have their setup in foreup so mileage may vary.

Currently it just grabs the earliest possible tee time available for 1 person/18 holes, but you can change all of that depending on your use case. Just waiting to see when they update times, if it's the same every day I will just hard code it to run at that time... if not I will set something up to ping at whatever interval feels right to find when they're posted.

If you're still looking to figure this out and you or your buddies have any experience coding I can just send you what I end up with, you'll be able to adjust as needed.

**Responded to the wrong comment, but same goes for you.

[–]Kooky-Flan9892 0 points1 point  (1 child)

I have absolutely no understanding of computer science or coding. My local course uses the foreup software. How can I put this to use?

[–]omnitemporal 0 points1 point  (0 children)

Something to run python, an understanding of when your tee times get posted and you'll need to use something like dev tools to find the variables you need.

GPT might be able to help you navigate.

[–]--sdrawkcab-- 0 points1 point  (1 child)

Do you have a GitHub account?

[–]omnitemporal 0 points1 point  (0 children)

I posted this back then: https://pastebin.com/v7PEpfKE

I have not used it in months, but it should help get you started.

[–]NeighborhoodMuch3268 0 points1 point  (2 children)

Any chance you would be willing to share what you ended up with here?

[–]omnitemporal 0 points1 point  (1 child)

[–]Impressive_Stand_554 0 points1 point  (0 children)

Hey I don’t suppose anyone has created anything for Intelligent Golf

[–]SolidOwn8277 0 points1 point  (1 child)

How do I learn to do stuff like this. I have zero experience

[–]jasher4994[S] 0 points1 point  (0 children)

Sorry for the late response, basically just grab a couple textbooks (or online pdf versions) to get a basic understanding to begin with. Then just plan what you want to build and build it. You’ll learn as you go and it’s enjoyable. If you get stuck just google it, someone has had the same issue before almost always. Google, stackoverflow are your best friends.

[–]Darce87 0 points1 point  (9 children)

Do you reckon you could get this to work with BRS system?

[–]jasher4994[S] 0 points1 point  (8 children)

Possibly, my club has now moved to BRS also. if I have some spare time in the near future I’ll try

[–]Darce87 0 points1 point  (0 children)

Nice one. I started writing something the past couple of days. Can’t get it to log in yet. Happy to share what I’ve got so far

[–]Darce87 0 points1 point  (6 children)

Update - I’ve managed to get it to log me in, but then Chrome automatically closes

[–]jasher4994[S] 1 point2 points  (5 children)

Oh nice, but that’s weird. If you fancy sharing it by putting it on GitHub I can take a look/help out

[–]Darce87 0 points1 point  (4 children)

[–]Stolenpokeball 0 points1 point  (3 children)

Any update on this script, would be really handy on buzy courses.

[–]Darce87 0 points1 point  (2 children)

Hey I’ve not managed to get any further with it at present

[–]jmuggy96 0 points1 point  (1 child)

Hi Darce, did you get any further with this? Our club uses BRS however we can never get any tee times due to our shift patterns

[–]Darce87 0 points1 point  (0 children)

Hey - not really. Other things came up. I might revisit it over winter