Code Monkey home page Code Monkey logo

resy-cli's Introduction

resy-cli

^ a happy resy-cli user getting exactly the reservation he wanted



Disclaimer: This document targets a non-technical audience. For a more technical version of this README, consult PERUSEME.md.

Table of Contents

About

resy-cli is a program to schedule a resy reservation booking to execute at exactly the right time in the future.

You might be asking, why would you do this? This is in fact a great question, as this project is utterly useless in low-demand markets where you're better off booking your reservation through resy's website. However in high-demand markets like NYC, reservation slots at top restaurants are snatched up in a matter of seconds.

After too many instances of losing to people who could click faster than me (or other programs ๐Ÿ˜…), I decided that enough was enough. While this project initially existed as a simple Node script, I wanted to make something that was easily distributable and usable by friends and family. A few weekends later, resy-cli was born.

Prerequisites

Terminal Familiarity

resy-cli is a command-line interface, and resultingly requires some familiarity with a terminal emulator.

If you are using a Mac computer, there are plenty of resources online to help get you started with the MacOS default terminal emulator (Terminal). This should give you a good foundation to set up resy-cli on your computer.

Homebrew Installation

resy-cli uses the Homebrew package manager for distribution on MacOS and Linux operating systems. Follow installation instructions from their homepage to install.

at Permissions

Under the hood, resy-cli uses another command-line interface called at to schedule reservations to book in the future.

While it's unnecessary to have an understanding of how at works in order to use resy-cli, it is necessary to follow some setup to activate this program on your machine. The following instructions are for MacOS (where at comes pre-installed). If you're using a different OS, these steps will vary (and you may have to install at separately).

  1. Execute the following command from your terminal emulator (this will prompt you for your computer's user credentials):
    sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist
    
  2. Navigate to System Preferences > Security & Privacy > Privacy
  3. Unlock to edit settings
  4. Add a new entry to "Full Disk Access"
  5. Press Cmd+Shift+G at the file selection dialog to select a custom path
  6. Add /usr/libexec/atrun to the list of commands/applications with "Full Disk Access"

Installation

To install resy-cli, run the following command from your terminal emulator:

brew install lgrees/lgrees/resy

If the install succeeded, you should see a success message in your terminal.

You can verify that the installation was successful by running the following command:

resy -v

If the command succeeds, you should see output like the following indicating the current version of resy-cli:

resy version 0.1.0

To view all of the commands that are available to you, run:

resy

Authentication Setup

In order to book reservations on your behalf, resy-cli needs to know about your resy account credentials. To add these, run:

resy setup

You'll be prompted to add an api key and an auth token. Follow these steps to find this information:

  1. Open a web browser
  2. Open Developer Tools (on Chrome: Chrome > View > Developer > Developer Tools)
  3. Navigate to resy and log in
  4. Open the "Network" tab with Developer Tools
  5. Search for requests to the domain: api.resy.com
  6. View the request headers

At this point, you should see something that looks like the following: Screen Shot 2022-11-08 at 6 33 31 PM

The obfuscated values associated with the keys highlighted in red are what you are looking for.

To verify that this setup was successful, run:

resy ping

If this command fails, it likely means that the credentials that you provided are incorrect. Repeat the authentication setup again to re-enter your credentials.

Once this command succeeds, you're ready to start booking!

NOTE: Resy will periodically expire your credentials. It's a good practice to run resy ping before booking to ensure that resy-cli can connect to your account.

Scheduling a Booking

Run:

resy schedule

Now follow the prompts to schedule your booking.

Booking Immediately

While scheduling a booking is the main intent of resy-cli, you may sometimes want to book immediately using the CLI (ex. when testing). resy book is an internal command that resy schedule uses under the hood which immediately books a reservation (analogous to clicking around in the resy UI). This command can be used in the following manner:

resy book --partySize=2 --reservationDate=2023-02-11 --reservationTimes=18:15:00  --venueId=123 --reservationTypes=""

Troubleshooting

resy-cli outputs a log file for every attempted booking (including dry runs). To view logs, run:

resy log view

Viewing log files will help to deduce what went wrong if resy-cli fails to book your desired reservation. Most often, this is due to your computer not being awake at the time of booking, or the restaurant not releasing any slots that match your criteria.

To remove all log files, run:

resy log clear

FAQ

Q: How are my resy credentials stored?
A: Credentials are written to disk on your local machine and are never shared (outside of making requests to resy).

Q: What about time zones?
A: resy-cli treats the booking time that you input as system times.

As an example, if you want to book at 5:00PM and your computer is set to use the eastern time zone, you will end up attempting to book at 5:00PM eastern.

Reservation times are localized to the location of the restaurant.

Q: What if my computer is turned off / asleep at the time when I want to book a reservation?
A: resy-cli books reservations using your local machine. If the machine is turned off / asleep, booking will not complete.

To circumvent this, you can schedule your computer to wake from sleep at the time of booking. On Mac, I've used the pmset CLI to accomplish this successfully.

Q: Are reservation services okay with this?
A: It's up to users to follow the (Terms of Service) set forth by resy. resy-cli is just a tool to automate your interactions with resy (no web scraping or anything of the sort).

Q: What happens when everyone is using programs like this? Won't this stop being effective?
A: Yes.

Q: I think I found a bug, how can I report it?
A: If you have a github account, feel free to submit an issue. If not, feel free to text me.

Q: This program literally changed my life, how can I possibly thank the author?
A: Consider taking him out to dinner ๐Ÿ™ƒ.

resy-cli's People

Contributors

lgrees avatar

Stargazers

Frank Harris avatar  avatar David Terei avatar  avatar Raphael Khaykin avatar CodingMogul avatar  avatar Flexagon avatar Mihir Patil avatar Hefei Tu avatar  avatar Jerry avatar Max Klein avatar  avatar Bowen Hou avatar Alex Hofmann avatar Pepi avatar Thomas avatar Ushio avatar  avatar Tiffany Trinh avatar  avatar  avatar  avatar OpenChampagne ๐Ÿพ avatar Tiger Shen avatar  avatar Tom Fitzpatrick avatar Sam Nanayakkara avatar  avatar Steph avatar M avatar

Watchers

 avatar Kyuhoon Kim avatar

resy-cli's Issues

Watch for openings between times

Hey there. This looks really good so far. It seems to be designed for restaurants that open slots in advance, but I wonder if it can be adapted to watch for openings and snipe them given some parameters.

I find most of my bookings by checking back constantly as people tend to cancel within days or hours of the rez. The resy notify functionality is usually too late (or I'm too slow).

For example, I'd like to get a table for 6 at popular restaurant XYZ between 5pm and 9pm. I'd like to be able to watch for openings and book one within the params as soon as it appears.

Wondering your thoughts, and happy to help!

Issue with missing header

Hi, I encountered an issue for reservations that require a pre-payment via credit card.

This is the error message: {"level":"warn","error":"Post "https://api.resy.com/3/details\": context deadline exceeded (Client.Timeout exceeded while awaiting headers)"

It works for the restaurants that don't require payment.

SlotTime in schedule

When scheduling a job, how do you know the time that the restaurant drops new slots? Some restaurants explicity say on their resy page, others don't.

Bot not quick enough?

Been trying to use this bot for a specific restaurant for a few days now, and it never is able to see any openings when it goes off at 9am. My guess is that the bot isn't quick enough when reservations open. It works fine for instant booking at restaurants with availability.

Does it still work?

Hey! I have a different resy bot that I've been using, but it stopped working recently. Did this happen to you too? I think they might have been restricting access or something. Thanks!

Venue reply invalid

Hi, I could be dumb but its not letting me enter my own venueId for schedule. Every time I try to enter the venueId number the bot gives me a "Sorry, your reply was invalid: please tab to search and select a venue" When I tab it only gives me a select few restaurants. I was able to book an immediate reservation, just could not use the schedule feature.

403 when trying to book

This is more of a question than a bug report: does a 403 just mean that the booking slot has already been claimed? Seems weird that the slots are still available when the job retries.

{"level":"info","booking_details":{"reservation_times":"19:00:00,19:15:00,19:30:00,19:45:00,20:00:00,18:45:00,18:30:00,18:15:00,18:00:00,20:15:00,20:30:00,20:45:00,21:00:00,21:15:00,21:30:00,17:45:00,17:30:00,17:15:00,17:00:00","reservation_types":"","reservation_date":"2024-07-19","party_size":"2","venue_id":"65452","booking_datetime":"2024-06-22 12:00:00"},"time":"2024-06-22T11:59:00-04:00","message":"starting book job"}
{"level":"info","time":"2024-06-22T11:59:00-04:00","message":"waiting 59 seconds until booking time: 2024-06-22 12:00:00"}
{"level":"info","available_slots":[{"reservation_time":"2024-07-19 17:00:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:30:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:45:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:30:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:45:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:00:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:30:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:45:00","reservation_type":"Dining Room"}],"time":"2024-06-22T12:00:00-04:00","message":"found available slots"}
{"level":"info","matching_slots":[{"reservation_time":"2024-07-19 17:00:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:30:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:45:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:30:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:45:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:00:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:30:00","reservation_type":"Dining Room"}],"time":"2024-06-22T12:00:00-04:00","message":"found matching slots"}
{"level":"info","slot":{"reservation_time":"2024-07-19 17:00:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 17:00:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 17:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 17:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 17:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 17:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 17:45:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 17:45:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 19:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 19:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 19:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 19:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 19:45:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 19:45:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 21:00:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 21:00:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 21:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 21:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 21:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 21:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:00-04:00","message":"booking slot failed"}
{"level":"error","error":"could not book any matching slots","time":"2024-06-22T12:00:00-04:00","message":"no booking occurred"}
{"level":"info","time":"2024-06-22T12:00:00-04:00","message":"retrying book job"}
{"level":"info","available_slots":[{"reservation_time":"2024-07-19 17:00:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:30:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:45:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:30:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:45:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:00:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:30:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:45:00","reservation_type":"Dining Room"}],"time":"2024-06-22T12:00:01-04:00","message":"found available slots"}
{"level":"info","matching_slots":[{"reservation_time":"2024-07-19 17:00:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:30:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 17:45:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:30:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 19:45:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:00:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:15:00","reservation_type":"Dining Room"},{"reservation_time":"2024-07-19 21:30:00","reservation_type":"Dining Room"}],"time":"2024-06-22T12:00:01-04:00","message":"found matching slots"}
{"level":"info","slot":{"reservation_time":"2024-07-19 17:00:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 17:00:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 17:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 17:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 17:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 17:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 17:45:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 17:45:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 19:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 19:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 19:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 19:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 19:45:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 19:45:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 21:00:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 21:00:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 21:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 21:15:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"booking slot failed"}
{"level":"info","slot":{"reservation_time":"2024-07-19 21:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"attempting to book slot"}
{"level":"warn","error":"failed to get booking details, status code: 403","slot":{"reservation_time":"2024-07-19 21:30:00","reservation_type":"Dining Room"},"time":"2024-06-22T12:00:01-04:00","message":"booking slot failed"}
{"level":"error","error":"could not book any matching slots","time":"2024-06-22T12:00:01-04:00","message":"no booking occurred"}

Resy made breaking changes to the book api

Noticed this when booking today. Changed from x-www-form-urlencoded to json. Results in a 404 error from the logs. Seems like a simple fix. Will work on this when I have some time.

412 Code

Does anyone know how to fix a 412 code here? Perhaps an issue with headers?

{"level":"warn","error":"failed to book reservation, status code: 412","slot":{"reservation_time":"2024-06-26 22:00:00","reservation_type":"Dinner"},"time":"2024-06-23T19:05:08-04:00","message":"booking slot failed"}

A few requests / issues

Hi lgrees, thank you for making resy-cli available to all and opensource.

I had a few questions / requests:

  • Currently it is very difficult to select the venue when scheduling, can it be made to just require the venue_id ?
  • Is there a way to delete scheduled bookings?
  • Is there a way to book using the 'resy schedule' command without having to go through the whole dialogue, perhaps so we can just add flags to the intial command?

Many thanks!

[RESOLVED] Venue search?

RESOLVED my issue here, please feel free to delete. Sorry for the clutter, and thanks for building!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.