Skip to content

Instantly share code, notes, and snippets.

@bf4
Forked from dbknickerbocker/southwest.user.js
Created January 14, 2016 15:11
Show Gist options
  • Save bf4/304cb75820d91b1aae47 to your computer and use it in GitHub Desktop.
Save bf4/304cb75820d91b1aae47 to your computer and use it in GitHub Desktop.
Southwest Auto Check-In
// ==UserScript==
// @name Southwest Auto Check-In
// @namespace http://dbknickerbocker.blogspot.com
// @description Automatically check-in for Southwest flights
// @include https://southwest.com/flight/retrieveCheckinDoc*
// @include https://www.southwest.com/flight/retrieveCheckinDoc*
// @include https://southwest.com/flight/selectPrintDocument*
// @include https://www.southwest.com/flight/selectPrintDocument*
// @updateURL https://gist.github.com/dbknickerbocker/5730976/raw/southwest.user.js
// @author David B. Knickerbocker
// @version 0.3
// ==/UserScript==
var SECOND_IN_MSEC = (1000);
var MINUTE_IN_MSEC = (SECOND_IN_MSEC * 60);
var HOUR_IN_MSEC = (MINUTE_IN_MSEC * 60);
var DAY_IN_MSEC = (HOUR_IN_MSEC * 24);
var TIMEOUT_MAX_MSEC = (DAY_IN_MSEC * 24);
function southwestCheckInForm() {
return document.getElementById('itineraryLookup');
}
function submitSouthwestCheckInForm() {
try {
southwestCheckInForm().submit();
} catch (exception) {
alert("Unknown error has occured - You're on your own! :" + exception.message);
}
}
function countdownDiv() {
return document.getElementById('countdown');
}
function insertBreak(element) {
element.appendChild(document.createElement('br'));
}
function insertText(element, text) {
element.appendChild(document.createTextNode(text));
}
function insertTextWithBoldStyle(element, text) {
var span = document.createElement('span');
span.style.fontWeight = 'bold';
insertText(span, text);
element.appendChild(span);
}
function removeAllChildrenFromElement(element) {
while (element.firstChild) {
element.removeChild(element.firstChild);
}
}
function zeroPad(value) {
return (value < 10) ? '0' + value : value;
}
function displayCountdown(checkInDate) {
try {
var countdown = countdownDiv();
removeAllChildrenFromElement(countdown);
var timeRemainingMsec = checkInDate - new Date();
if (timeRemainingMsec <= 0) {
insertTextWithBoldStyle(countdown, 'Checking in now...');
insertBreak(countdown);
return;
}
var days = Math.floor(timeRemainingMsec / DAY_IN_MSEC);
var hours = Math.floor(timeRemainingMsec / HOUR_IN_MSEC) % 24;
var minutes = Math.floor(timeRemainingMsec / MINUTE_IN_MSEC) % 60;
var seconds = Math.floor(timeRemainingMsec / SECOND_IN_MSEC) % 60;
insertBreak(countdown);
insertTextWithBoldStyle(countdown, 'Check-in time: ');
insertText(countdown, checkInDate.toString());
insertBreak(countdown);
insertTextWithBoldStyle(countdown, 'Time remaining until automatic check-in: ');
insertText(countdown, zeroPad(days) + ' DAY ' + zeroPad(hours) + ' HRS ' + zeroPad(minutes) + ' MIN ' + zeroPad(seconds) + ' SEC');
insertBreak(countdown);
insertBreak(countdown);
} catch (exception) {
alert("Unknown error has occured - You're on your own! :" + exception.message);
}
}
function elementByIdValueAsInteger(id) {
return parseInt(document.getElementById(id).value, 10);
}
function getFlightDate() {
var month = elementByIdValueAsInteger('month-input') - 1;
var day = elementByIdValueAsInteger('day-input');
var year = elementByIdValueAsInteger('year-input');
var hours = elementByIdValueAsInteger('hour-input');
var minutes = elementByIdValueAsInteger('minute-input');
var seconds = elementByIdValueAsInteger('second-input');
var flightDate = new Date(year, month, day, hours, minutes, seconds, 0);
if ((flightDate.getMonth() != month) || (flightDate.getDate() != day) || (flightDate.getFullYear() != year) ||
(flightDate.getHours() != hours) || (flightDate.getMinutes() != minutes) || (flightDate.getSeconds() != seconds)) {
return null;
}
return flightDate;
}
function displayUnderOneHourError() {
insertAutoCheckInFormWithError('Unable to check-in when flight is within one hour.');
}
function displayInvalidDateError() {
insertAutoCheckInFormWithError('Invalid Date!');
}
function displayMaxTimeoutError() {
var maxFlightDateToSatisfyMaxTimeout = new Date(new Date().getTime() + TIMEOUT_MAX_MSEC + DAY_IN_MSEC);
insertAutoCheckInFormWithError('Your flight must be before: ' + maxFlightDateToSatisfyMaxTimeout);
}
function displayFlightInPastError(flightDate) {
insertAutoCheckInFormWithError('You already missed your flight: ' + flightDate);
}
function startAutoCheckInCountdown() {
try {
var flightDate = getFlightDate();
if (flightDate === null) {
displayInvalidDateError();
return;
}
var timeRemainingToFlightMsec = (flightDate - new Date());
if (timeRemainingToFlightMsec < 0) {
displayFlightInPastError(flightDate);
return;
}
if (timeRemainingToFlightMsec <= HOUR_IN_MSEC) {
displayUnderOneHourError();
return;
}
if (timeRemainingToFlightMsec <= DAY_IN_MSEC) {
submitSouthwestCheckInForm();
return;
}
var timeRemainingToCheckInMsec = timeRemainingToFlightMsec - DAY_IN_MSEC;
if (timeRemainingToCheckInMsec > TIMEOUT_MAX_MSEC) {
displayMaxTimeoutError();
return;
}
var checkInDate = new Date(flightDate.getTime() - DAY_IN_MSEC);
window.setTimeout(submitSouthwestCheckInForm, timeRemainingToCheckInMsec);
window.setInterval(function () {
displayCountdown(checkInDate);
}, SECOND_IN_MSEC);
} catch (exception) {
alert("Unknown error has occured - You're on your own! :" + exception.message);
}
}
function insertInput(element, id, value, length) {
var input = document.createElement('input');
input.id = id;
input.type = 'text';
input.maxLength = length;
input.size = length;
input.value = value;
input.setAttribute('onfocus', "if (this.value === '" + value + "') { this.value = ''; }");
element.appendChild(input);
}
function insertLabel(element, text, id) {
var label = document.createElement('label');
label.setAttribute('for', id);
label.textContent = text;
element.appendChild(label);
}
function insertH4(element, text) {
var h4 = document.createElement('h4');
h4.textContent = text;
element.appendChild(h4);
return h4;
}
function insertH4WithColor(element, text, color) {
var h4 = insertH4(element, text);
h4.style.color = color;
}
function createAutoCheckInForm() {
var autoCheckInForm = document.createElement('form');
autoCheckInForm.setAttribute('method', 'POST');
insertH4(autoCheckInForm, 'When is your flight?');
insertBreak(autoCheckInForm);
insertLabel(autoCheckInForm, 'Date: ', 'month-input');
insertInput(autoCheckInForm, 'month-input', 'mm', '2');
insertText(autoCheckInForm, '/');
insertInput(autoCheckInForm, 'day-input', 'dd', '2');
insertText(autoCheckInForm, '/');
insertInput(autoCheckInForm, 'year-input', 'yyyy', '4');
insertBreak(autoCheckInForm);
insertLabel(autoCheckInForm, 'Time (24 hr): ', 'hour-input');
insertInput(autoCheckInForm, 'hour-input', 'hh', '2');
insertText(autoCheckInForm, ':');
insertInput(autoCheckInForm, 'minute-input', 'mm', '2');
insertText(autoCheckInForm, ':');
insertInput(autoCheckInForm, 'second-input', 'ss', '2');
insertBreak(autoCheckInForm);
insertBreak(autoCheckInForm);
var startAutoCheckInButton = document.createElement('input');
startAutoCheckInButton.id = 'auto-check-in-button';
startAutoCheckInButton.type = 'button';
startAutoCheckInButton.value = 'Start Auto Check-In';
startAutoCheckInButton.addEventListener('click', startAutoCheckInCountdown, true);
autoCheckInForm.appendChild(startAutoCheckInButton);
return autoCheckInForm;
}
function insertChildBefore(child, element) {
element.parentNode.insertBefore(child, element);
}
function removePreviousCountdownDiv() {
var countdown = countdownDiv();
if ((countdown !== null) && (countdown.parentNode !== null)) {
countdown.parentNode.removeChild(countdown);
}
}
function insertCountdownDivWithElements(elements) {
removePreviousCountdownDiv();
var countdownDiv = document.createElement('div');
countdownDiv.id = 'countdown';
countdownDiv.style.backgroundColor = '#F3F5FF';
countdownDiv.style.borderRadius = '10px';
countdownDiv.style.padding = '20px';
for (var i = 0; i < elements.length; ++i) {
countdownDiv.appendChild(elements[i]);
}
insertChildBefore(countdownDiv, southwestCheckInForm());
}
function createErrorNode(error) {
var div = document.createElement('div');
insertH4WithColor(div, error, 'red');
insertBreak(div);
return div;
}
function insertAutoCheckInFormWithError(error) {
insertCountdownDivWithElements([createErrorNode(error), createAutoCheckInForm()]);
}
function insertAutoCheckInForm() {
insertCountdownDivWithElements([createAutoCheckInForm()]);
}
function countdownDivPresent() {
return (countdownDiv() !== null);
}
function checkForDepartureTimeOops() {
try {
var errorsUl = document.querySelector('ul#errors');
if (errorsUl === null) {
return;
}
var errors = errorsUl.getElementsByTagName('li');
for (var i = 0; i < errors.length; ++i) {
if (errors[i].textContent.indexOf('more than 24 hours prior') >= 0) {
insertAutoCheckInForm();
break;
}
}
} catch (exception) {
alert("Unknown error has occured - You're on your own! :" + exception.message);
}
}
function selectAllPassengers() {
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; ++i) {
var input = inputs[i];
if (input.getAttribute('type') == 'checkbox') {
input.checked = true;
}
}
}
function printDocuments() {
try {
var printButton = document.getElementById('printDocumentsButton');
if (printButton === null) {
return;
}
selectAllPassengers();
printButton.click();
} catch (exception) {
alert("Unknown error has occured - You're on your own! :" + exception.message);
}
}
if (document.location.href.indexOf('retrieveCheckinDoc') >= 0) {
if (!countdownDivPresent()) {
checkForDepartureTimeOops();
}
} else if (document.location.href.indexOf('selectPrintDocument') >= 0) {
printDocuments();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment