// ==UserScript==
// @name iRacing Auto Join
// @version 2.1.1
// @author Paul Ilbrink
// @copyright 2012 - 2019, Paul Ilbrink
// @namespace http://www.paulilbrink.nl/userscripts
// @description This script adds an auto join checkbox after registering for an iRacing session. Once a green join button becomes available it will be automatically clicked if the checkbox is ticked.
// @match *://members.iracing.com/membersite/member/*
// @exclude *://members.iracing.com/membersite/member/EventResult*
// @exclude *://members.iracing.com/membersite/member/JoinedRace.do
// @grant none
// ==/UserScript==
var script = document.createElement("script");
script.textContent = "(" + PI_iRacingAutoJoin.toString() + ")();";
document.body.appendChild(script);
function PI_iRacingAutoJoin() {
// add css styles to the page
PI_addStyle = function (css) {
var style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
};
// https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
PI_getUuid = function () {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
};
PI_AUTO_JOIN = {
key: 'PI_AUTO_JOIN',
settings: {
autoJoinChecked: false,
autoJoinPreSessionPractice: false,
sessionJoined: -1,
uid: null
},
checkbox: null,
uid: PI_getUuid(),
// initializes auto join
INIT: function () {
var thiz = this;
thiz.setupListeners();
thiz.loadSettings();
thiz.addSettings();
},
// addding settings dialog
addSettings: function () {
var thiz = this;
$('<span class="icon icon-gear"></span>').css({
position: 'absolute',
top: 40,
right: 7,
color: 'gold',
cursor: 'pointer'
}).on('click', function () {
var settingsHtml = '<div id=piAjSettings>';
settingsHtml += '<h3>iRacing Auto Join settings</h3>';
if (!thiz.checkbox) {
settingsHtml += '<label><input type=checkbox class=piAjCheckbox';
settingsHtml += (thiz.settings.autoJoinChecked ? ' checked=checked' : '');
settingsHtml += ' /> Auto join enabled?</label>';
}
settingsHtml += '<label><input type=checkbox class=piAjPreSessionPractice';
settingsHtml += (thiz.settings.autoJoinPreSessionPractice ? ' checked=checked' : '');
settingsHtml += ' /> Join pre-session practice? (if available)</label>';
settingsHtml += '</div>';
iRacingAlerts(settingsHtml);
}).appendTo('#racingpanel_inner');
},
// setup various listeners
setupListeners: function () {
var thiz = this;
// local storage listener - stay up to date with changes made in other windows/tabs
$(window).on('storage', function (e) {
if (e.originalEvent.key === thiz.key) {
lightsOn();
// tiny delay, because Edge sucks
setTimeout(function () {
thiz.loadSettings();
}, 50);
}
});
// pre session setting
$(document).on('change', '.piAjPreSessionPractice', function () {
thiz.settings.autoJoinPreSessionPractice = this.checked;
thiz.saveSettings();
});
// monitor the auto join checkbox
$(document).on('change', '.piAjCheckbox', function (e) {
e.stopPropagation();
thiz.settings.autoJoinChecked = this.checked;
if (!thiz.settings.autoJoinChecked) {
// manually unchecked the checkbox, so reset hasJoinedBefore?
thiz.settings.sessionJoined = -1;
}
thiz.saveSettings();
});
},
// add checkbox to the page
showCheckbox: function (data) {
var thiz = this;
if (thiz.checkbox) {
return;
}
thiz.checkbox = $('<input type=checkbox class=piAjCheckbox />').css({
position: 'absolute',
top: 37,
right: 27
}).attr(
'checked', thiz.settings.autoJoinChecked
).appendTo('#racingpanel_inner');
},
// remove checkbox
cleanupCheckbox: function (data, notRegisteredAnymore) {
var thiz = this;
if (thiz.checkbox) {
thiz.checkbox.remove();
thiz.checkbox = null;
}
// no longer registered, so no need to prevent re-joining previous session anymore
if (notRegisteredAnymore) {
thiz.settings.sessionJoined = -1;
thiz.saveSettings();
}
},
// join button becomes available, handle appropriately
clickJoinButton: function (data) {
var thiz = this;
var isActualSession = data.sessionid === data.targetsessionid;
var canJoin = thiz.settings.autoJoinChecked &&
(isActualSession || thiz.settings.autoJoinPreSessionPractice);
if (canJoin) {
setTimeout(function () {
var hasJoinedBefore = data.sessionid === thiz.settings.sessionJoined;
var joinButton = $('#racingpanel_session a.brand-success');
if (hasJoinedBefore) {
joinButton.text('Click yourself this time…');
} else {
thiz.settings.sessionJoined = data.sessionid;
thiz.settings.uid = thiz.uid;
joinButton.text('Auto join in progress...');
thiz.saveSettings();
joinButton.trigger('click');
thiz.cleanupCheckbox();
}
}, 250);
} else if (!isActualSession && !thiz.settings.autoJoinPreSessionPractice) {
// there is a pre session practice, so wait for the actual session
} else {
// auto join not checked, leave checkbox there for now...
}
},
// load auto join settings from local storage
loadSettings: function () {
var thiz = this;
// keep track of window/tab uuid
var sessionUid = window.sessionStorage.getItem(thiz.key);
if (sessionUid) {
thiz.uid = sessionUid;
} else {
sessionStorage.setItem(thiz.key, thiz.uid);
}
// load settings from local storage
var storageSettings = localStorage.getItem(thiz.key);
if (storageSettings) {
try {
$.extend(thiz.settings, JSON.parse(storageSettings));
if (thiz.checkbox && thiz.checkbox.checked !== thiz.settings.autoJoinChecked) {
thiz.checkbox.attr('checked', thiz.settings.autoJoinChecked);
}
} catch (err) {
console.error('an error occurred while parsing the storageSettings', storageSettings, err);
return false;
}
}
},
// save auto join settings to local storage
saveSettings: function () {
var thiz = this;
thiz.settings.uid = thiz.uid;
localStorage.setItem(thiz.key, JSON.stringify(thiz.settings));
sessionStorage.setItem(thiz.key, thiz.uid);
},
// monitor changes in registration status on the iracing member site
monitorRegistrationStatus: function (data) {
var thiz = this;
if (data) {
switch (data.status) {
case racingpaneldata.sessionstatus.ok_to_join: // 3
thiz.showCheckbox(data);
thiz.clickJoinButton(data);
break;
case racingpaneldata.sessionstatus.registered: // 1
case racingpaneldata.sessionstatus.assigned: // 5
thiz.showCheckbox(data);
break;
case racingpaneldata.sessionstatus.do_not_join: // 2 - is this correct, no idea?
case racingpaneldata.sessionstatus.joined: // 4
thiz.cleanupCheckbox(data, false);
break;
case racingpaneldata.sessionstatus.withdrawn: // 6
case racingpaneldata.sessionstatus.rejected: // 7
case - 1: // reg_none | You are not registered for any event.
thiz.cleanupCheckbox(data, true);
break;
default:
console.error('[auto join] unknown sessionstatus', data.status, data.regStatus);
break;
}
} else {
// not registered at all
thiz.cleanupCheckbox('empty registration status object');
}
}
};
// check if there even is a control panel
if (IRACING.control_panels) {
// add auto join styling
PI_addStyle('#piAjSettings label { text-align:left; display:block; }');
// init auto join
PI_AUTO_JOIN.INIT();
// interecepting iracing triggers to detect session registration status
IRACING.control_panels.OrgShowRegistrationStatus = IRACING.control_panels.showRegistrationStatus;
IRACING.control_panels.showRegistrationStatus = function (data) {
try {
PI_AUTO_JOIN.monitorRegistrationStatus(data);
} catch (err) {
console.err('an error occured while processing PI_AUTO_JOIN', err);
}
this.OrgShowRegistrationStatus(data);
};
}
}