Skip to content

Instantly share code, notes, and snippets.

@itdependsnetworks
Last active November 15, 2019 16:03
Show Gist options
  • Save itdependsnetworks/be51e8cbba68b5c145cb0ce90804675d to your computer and use it in GitHub Desktop.
Save itdependsnetworks/be51e8cbba68b5c145cb0ce90804675d to your computer and use it in GitHub Desktop.
TSA Global Entry Appointment Finder to Slack

Requirements

Docker

Build process

  • Update the details.yml to your spec
  • Run the command make run to build and run container. You can rebuild with same command
    • It may be helpful to create a cache layer by creating a Dockerfile without the ADD and Entrypoint keywords
  • Run "make logs" to see output of logs
  • Run "make destroy" to stop the application

DUMMY DATA FOR GIST NAME

# To get your token just go to https://api.slack.com/custom-integrations/legacy-tokens Scroll down to the "Legacy information" section and click Issue token/Re-issue token
TOKEN: "xoxp-XXXXXXXXXXX-XXXXXXXXXXX-XXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# To obtain the Channel ID, Right-Click on the channel, or direct message and click copy link. The id is the last part of that link
# e.g. https://your_org.slack.com/archives/YOUR_CHANNEL_ID
CHANNEL: "YOUR_CHANNEL_ID"
# Obtain from https://ttp.cbp.dhs.gov/schedulerapi/slots/asLocations?limit=100 and getting the "id"
# Key is just your local name to reference in output
LOCATION_IDS:
JFK: 5140
Newark: 5444
# The date in format of YYYY-MM-DD
DATE_BEFORE: '2019-11-16'
# Time to wait in seconds
TIME_WAIT: 10
FROM python:3.6.7-jessie
RUN pip install requests slackclient pyyaml
ADD tsa.py ./
ADD details.yml ./
ENTRYPOINT python tsa.py
.PHONY: run
run:
docker container rm -f tsa || true
docker image rm -f tsa || true
docker build -t tsa .
docker run -itd --name tsa tsa .
.PHONY: logs
logs:
docker logs -f tsa
.PHONY: destroy
destroy:
docker container rm -f tsa || true
#!/usr/bin/env python
import time
import sys
from datetime import datetime, timedelta
import yaml
import requests
import slack
INFO = yaml.safe_load(open('details.yml', 'r'))
TOKEN = INFO['TOKEN']
DATE_BEFORE = INFO['DATE_BEFORE']
CHANNEL = INFO["CHANNEL"]
TIME_WAIT = INFO["TIME_WAIT"]
LOCATION_IDS = INFO["LOCATION_IDS"]
# Idea and details located here.
# https://packetlife.net/blog/2019/aug/7/apis-real-life-snagging-global-entry-interview/
# Updated by clay584 https://gist.github.com/clay584/bcbbe3803ca6414ce09426a2c3d4abfb
# Converted from SMS to slack by Ken Celenza (itdependsnetworks)
# API URL
APPOINTMENTS_URL = "https://ttp.cbp.dhs.gov/schedulerapi/slots?orderBy=soonest&limit=1&locationId={}&minimum=1"
# Dates
now = datetime.now()
future_date = datetime.strptime(DATE_BEFORE, '%Y-%m-%d')
FOUND = dict([(val, {}) for val in LOCATION_IDS.values()])
#Post new message to slack channel in question
def post_to_slack(message):
client = slack.WebClient(token=TOKEN)
client.chat_postMessage(
channel=CHANNEL,
text=message)
def check_appointments(city, id):
url = APPOINTMENTS_URL.format(id)
appointments = requests.get(url).json()
return appointments
def appointment_in_timeframe(now, future_date, appointment_date):
if now <= appt_datetime <= future_date:
return True
else:
return False
try:
while True:
for city, id in LOCATION_IDS.items():
match = False
try:
appointments = check_appointments(city, id)
except Exception as e:
print("Could not retrieve appointments from API.")
appointments = []
appointment = next(iter(appointments), {"startTimestamp": "2200-12-12T00:00"})
start_time = appointment['startTimestamp']
appt_datetime = datetime.strptime(start_time, '%Y-%m-%dT%H:%M')
if appointment_in_timeframe(now, future_date, appt_datetime):
message = "{}: Found an appointment at {}!".format(city, start_time)
match = True
if not FOUND[id].get(start_time):
try:
post_to_slack(message)
print(message, "Sent Slack successfully! {}".format(message))
FOUND[id][start_time] = 1
except Exception as e:
print(e)
print(message, "Failed to send slack")
print(message)
else:
print("{}: No appointments before {}.".format(city, future_date))
if match is False and len(list(FOUND[id].keys())) > 0:
try:
message = "{}: No longer found an appointment at {}".format(city, list(FOUND[id].keys())[0])
post_to_slack(message)
print(message)
FOUND[id] = {}
except Exception as e:
print(e)
print(message, "Failed to send slack")
time.sleep(1)
time.sleep(TIME_WAIT)
except KeyboardInterrupt:
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment