Skip to content

Instantly share code, notes, and snippets.

@JamesIves
Last active June 8, 2023 11:33
Show Gist options
  • Save JamesIves/2b92c80844a39bc9d69a53a1c2edfbd7 to your computer and use it in GitHub Desktop.
Save JamesIves/2b92c80844a39bc9d69a53a1c2edfbd7 to your computer and use it in GitHub Desktop.
Sends a text message using Twilio when an appointment becomes available for a given location id on the CBP Trusted Traveler Program appointment scheduler for Global Entry. You must set the environment variables found in this file before it will work correctly, these can be found on the Twilio dashboard when you sign up for a free trial.
/**
* Maps out known airport codes to location ids.
*/
const LocationId = {
JFK: 5120,
EWR: 5444,
};
/**
* Gets the airport code for the location id.
* @param {number} locationId - The location id for the airport.
* @returns Returns the airport code for the location id.
*/
const getAirportCode = (locationId) =>
Object.keys(LocationId).find((key) => LocationId[key] === locationId);
/**
* Gets all available appointments from the TTP CBP API.
* @param {number[]} localIds - An array of location ids you'd like to fetch appointments for.
* @param {number} limit - The maximum amount of appointments you'd like to fetch for each location id.
* @returns Returns an array of available appointments.
*/
const getAvailableAppointments = async ({ locationIds, limit }) => {
const allAppointments = [];
await Promise.all(
locationIds.map(async (locationId) => {
const response = await fetch(
`https://ttp.cbp.dhs.gov/schedulerapi/slots?orderBy=soonest&limit=${limit}&locationId=${locationId}&minimum=1`
);
const data = await response.json();
const availableAppointments = data.map((appointment) => ({
location: getAirportCode(appointment.locationId),
start: new Date(appointment.startTimestamp).toLocaleString("en-GB", {
timeZone: "America/New_York",
}),
end: new Date(appointment.endTimestamp).toLocaleString("en-GB", {
timeZone: "America/New_York",
}),
}));
allAppointments.push(...availableAppointments);
})
);
return allAppointments;
};
/**
* Send a a text message with the Twilio API to inform the user of an available appointment.
* @param {*} appointments
* @returns {void}
*/
const sendTextMessage = async (appointment) => {
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const client = require("twilio")(accountSid, authToken);
await client.messages.create({
body: `There is a TTP appointment available at ${appointment.location} on ${appointment.start}! ✈️ 📅`,
from: process.env.TWILIO_PHONE_NUMBER,
to: process.env.MY_PHONE_NUMBER,
});
};
/**
* Initializes the script.
* @returns {void}
*/
const init = async () => {
console.log("Checking for appointments...");
const appointments = await getAvailableAppointments({
locationIds: [LocationId.JFK, LocationId.EWR],
limit: 1,
});
if (appointments.length) {
/** If you don't want to use Twilio, you can replace this part with your own notification system. */
appointments.map((appointment) => sendTextMessage(appointment));
} else {
console.log("No appointments found.");
}
};
console.log("Starting appointment checker...");
/**
* Runs the script every 5 minutes.
*/
setInterval(init, 300000);
{
"name": "appointment",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "James Ives",
"license": "ISC",
"dependencies": {
"twilio": "^4.11.2"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment