Last active
March 2, 2021 03:51
-
-
Save jimmygle/293417ed2acd61deec0c53993c12a360 to your computer and use it in GitHub Desktop.
Creates and shows reservations for the anytime fitness reserver tool at reserve.anytimefitness.com. It takes too long, so this is a simple ruby script to do it via CLI.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'net/http' | |
require 'uri' | |
require 'json' | |
require 'thor' | |
require 'date' | |
require 'pry' | |
ENV['THOR_SILENCE_DEPRECATION'] = '1' | |
class GymReservation < Thor | |
desc "reserve DATE at HOUR", 'eg today at noon, tue at 4pm, monday at 2p' | |
def reserve(date, at, hour) | |
abort('ERROR: Format must be "DATE at HOUR" (eg today at 5pm)') if at != 'at' | |
date_string = "%s %s %s" % [ _convert_date(date).to_s, _convert_hour(hour), Time.now.strftime("%:z") ] | |
parsed = DateTime.strptime(date_string, "%Y-%m-%d %l%P %Z") | |
epoch = parsed.to_time.to_i * 1000 | |
reserved = _reserve(epoch) | |
if reserved['error'] | |
puts "ERROR: #{reserved['error']}" | |
puts "Edit reservations: https://reserve.anytimefitness.com/reservations" | |
else | |
puts "Reservation successfully set for: #{parsed.strftime('%A, %B %-d, %Y at %-I%P')}" | |
end | |
end | |
desc 'reservations', 'shows current reservations' | |
def reservations | |
rs = _reservations | |
next_reservation = Time.at(rs['results'].first['start_int'] / 1000).utc.localtime | |
if next_reservation > Time.now | |
puts "Next reservation: #{next_reservation.strftime('%A, %B %-d, %Y at %-I%P')}" | |
else | |
puts "No current reservations." | |
end | |
end | |
no_commands do | |
def _convert_date(date) | |
case date | |
when 'today' | |
return Date.today | |
when 'tomorrow' | |
return Date.today.next_day | |
else | |
begin | |
d = Date.parse(date) | |
if ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun', 'monday', 'tuesday', 'thursday', 'friday', 'saturday', 'sunday'].include?(date.downcase) | |
return Date.today > d ? d + 7 : d | |
end | |
return d | |
rescue => error | |
puts "Invalid date: #{date}" | |
puts "Must be: today, tomorrow, mon, tuesday, or 2021-01-01 formats" | |
exit! | |
end | |
end | |
end | |
def _convert_hour(hour) | |
h = hour.gsub(/^(\d{1,2})(p|a)$/, '\\1\\2m') | |
unless h =~ /^\d{1,2}(am|pm)?$/ | |
puts "Invalid hour: #{hour}" | |
puts "Must be: 9, 9a, 9am, 9p, 9pm" | |
exit! | |
end | |
h += 'am' if h =~ /^\d{1,2}$/ | |
return h | |
end | |
def _reserve(date) | |
uri = URI.parse("https://api.muuvlabs.com/anytime/reservations") | |
request = Net::HTTP::Post.new(uri) | |
request.content_type = "application/json" | |
request["Authority"] = "api.muuvlabs.com" | |
request["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.152 Safari/537.36" | |
request["Cookieproxy"] = "---POPULATE ME FROM BROWSER SESSION---" | |
request["Accept"] = "*/*" | |
request["Sec-Gpc"] = "1" | |
request["Origin"] = "https://reserve.anytimefitness.com" | |
request["Sec-Fetch-Site"] = "cross-site" | |
request["Sec-Fetch-Mode"] = "cors" | |
request["Sec-Fetch-Dest"] = "empty" | |
request["Referer"] = "https://reserve.anytimefitness.com/" | |
request["Accept-Language"] = "en-US,en;q=0.9" | |
request.body = {club_ident: "---GET THIS FROM BROWSER---", start_int: date}.to_json | |
req_options = { | |
use_ssl: uri.scheme == "https", | |
} | |
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http| | |
http.request(request) | |
end | |
return JSON.parse(response.body) | |
end | |
def _reservations | |
uri = URI.parse("https://api.muuvlabs.com/anytime/reservations?include_club=1&per_page=500&ran=1614655270209") | |
request = Net::HTTP::Get.new(uri) | |
request.content_type = "application/json" | |
request["Authority"] = "api.muuvlabs.com" | |
request["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.152 Safari/537.36" | |
request["Cookieproxy"] = "---POPULATE ME FROM BROWSER SESSION---" | |
request["Accept"] = "*/*" | |
request["Sec-Gpc"] = "1" | |
request["Origin"] = "https://reserve.anytimefitness.com" | |
request["Sec-Fetch-Site"] = "cross-site" | |
request["Sec-Fetch-Mode"] = "cors" | |
request["Sec-Fetch-Dest"] = "empty" | |
request["Referer"] = "https://reserve.anytimefitness.com/" | |
request["Accept-Language"] = "en-US,en;q=0.9" | |
req_options = { | |
use_ssl: uri.scheme == "https", | |
} | |
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http| | |
http.request(request) | |
end | |
return JSON.parse(response.body) | |
end | |
end | |
end | |
GymReservation.start(ARGV) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment