import requests | |
from pytz import timezone | |
from datetime import datetime | |
from twilio.rest import Client | |
import json | |
import os | |
import sys | |
def login(): | |
# cURL login | |
# POST https://costcotireappointments.ca/login | |
try: | |
response = requests.post( | |
url="https://costcotireappointments.ca/login", | |
headers={ | |
"Origin": "https://costcotireappointments.ca", | |
"Accept-Encoding": "gzip, deflate, br", | |
"X-Csrf-Token": "Not sure this is necessary but include it, why not!", | |
"Accept-Language": "en-US,en;q=0.9,fr;q=0.8", | |
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36", | |
"Content-Type": "application/json;charset=UTF-8", | |
"Accept": "application/json, text/plain, */*", | |
"Referer": "https://costcotireappointments.ca/login", | |
"X-Requested-With": "XMLHttpRequest", | |
"Connection": "keep-alive", | |
}, | |
verify=False, | |
data=json.dumps({ | |
"email": "REPLACE_WITH_YOUR@EMAIL.COM", | |
"errorText": "", | |
"password": os.environ['PASSWORD'] # | |
}) | |
) | |
return response.json()['token'] | |
except requests.exceptions.RequestException: | |
print('Login Request failed') | |
def send_request(loc_id, token): | |
# cURL oil and tires | |
# GET https://costcotireappointments.ca/api/appointments/get-open-slots | |
# get today's date | |
tz = timezone('US/Eastern') | |
now = datetime.now(tz) | |
# create date string | |
date_string = "%s%s%s" % (now.year, now.month, now.day) | |
print("Beginning search for %s, with location %s" % (date_string, loc_id)) | |
try: | |
response = requests.get( | |
url="http://costcotireappointments.ca/api/appointments/get-open-slots", | |
params={ | |
"location_id": loc_id, # 1889 is local | |
"addon_ids[]": "32", | |
"service_id": "43", | |
"start_date": date_string, | |
"daysIncrement": "25", | |
}, | |
verify=False, | |
headers={ | |
"Authorization": "Bearer %s" % token, | |
"Accept-Encoding": "gzip, deflate, br", | |
"X-Csrf-Token": "Not sure this is necessary but include it, why not!", | |
"Accept-Language": "en-US,en;q=0.9,fr;q=0.8", | |
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36", | |
"Accept": "application/json, text/plain, */*", | |
"Referer": "https://costcotireappointments.ca/booking/service-day", | |
"X-Requested-With": "XMLHttpRequest", | |
}, | |
) | |
except requests.exceptions.RequestException as exc: | |
print('HTTP Request failed') | |
# parse response | |
days = response.json()['data'] | |
textable_days = "" | |
for day in days: | |
try: | |
day['num_slots'] | |
# didn't find anything | |
except KeyError: | |
available_date = day['prettyDate'] | |
available_time = day['start_time'] | |
textable_str = "%s at %s, for location %s. \n" % (available_date, available_time, day['c_id']) | |
if len(textable_days) < 100: | |
textable_days = textable_days + textable_str | |
else: | |
break | |
if len(textable_days) > 0: | |
send_message(textable_days) | |
else: | |
print("Nothing found for %s." % (loc_id)) | |
def send_message(text): | |
print("Sending '%s'" % (text)) | |
account_sid = 'TWILIO_ACCOUNT_SID' | |
auth_token = 'TWILIO_AUTH_TOKEN' | |
client = Client(account_sid, auth_token) | |
message = client.messages.create( | |
from_='YOUR_TWILIO_NUMBER', | |
to='YOUR_OWN_NUMBER', | |
body=text | |
) | |
print(message.sid) | |
if __name__ == "__main__": | |
loc_names = sys.argv[1:] | |
token = login() | |
for loc_id in loc_names: | |
send_request(loc_id, token) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment