Last active
October 13, 2016 19:09
-
-
Save dbknickerbocker/5730976 to your computer and use it in GitHub Desktop.
Southwest Auto Check-In
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
// ==UserScript== | |
// @name Southwest Auto Check-In | |
// @namespace http://dbknickerbocker.blogspot.com | |
// @description Automatically check-in for Southwest flights | |
// @include http://southwest.com/flight/retrieveCheckinDoc* | |
// @include http://www.southwest.com/flight/retrieveCheckinDoc* | |
// @include http://southwest.com/flight/selectPrintDocument* | |
// @include http://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