T.T. Hunter
T.T. Hunter
/*
* T.T. Hunter,
* -- hunts a TLS appointment.
* @version: 1.7
* @author:
* https://www.termin-tracker-all.com
*/
const centerInfo= {
'TlsGermanyRabat_FamilyVisit': {
'code': 'maRBA2de',
'country': 'de',
'aptType': 'court_sejour',
'issueCountry': 'ma'
},
'TlsGermanyRabat_Tourism': {
'code': 'maRBA2de',
'country': 'de',
'aptType': 'tourism',
'issueCountry': 'ma'
},
'TlsFranceFes_Case1': {
'code': 'maFEZ2fr',
'country': 'fr',
'aptType': 'Primo',
'issueCountry': 'ma'
},
'TlsFranceFes_Case2': {
'code': 'maFEZ2fr',
'country': 'fr',
'aptType': 'Renouvellement',
'issueCountry': 'ma'
},
'TlsFranceOujda_Case1': {
'code': 'maOUD2fr',
'country': 'fr',
'aptType': 'Primo',
'issueCountry': 'ma'
},
'TlsFranceOujda_Case2': {
'code': 'maOUD2fr',
'country': 'fr',
'aptType': 'Renouvellement',
'issueCountry': 'ma'
},
'TlsFranceCasablanca_Case1': {
'code': 'maCAS2fr',
'country': 'fr',
'aptType': 'Grand%20Public%20PRIMO',
'issueCountry': 'ma'
},
'TlsFranceCasablanca_Case2': {
'code': 'maCAS2fr',
'country': 'fr',
'aptType': 'Grand%20Public%20VISE',
'issueCountry': 'ma'
},
'TlsFranceCasablanca_Case3': {
'code': 'maCAS2fr',
'country': 'fr',
'aptType': 'Grand%20Public%20CIRCULATION',
'issueCountry': 'ma'
},
'TlsFranceTanger_Case1': {
'code': 'maTNG2fr',
'country': 'fr',
'aptType': 'PRIMO',
'issueCountry': 'ma'
},
'TlsFranceAgadir_Case1': {
'code': 'maAGA2fr',
'country': 'fr',
'aptType': 'Grand%20Public%20PRIMO',
'issueCountry': 'ma'
},
'TlsFranceMarrakech_Case1': {
'code': 'maRAK2fr',
'country': 'fr',
'aptType': 'Grand%20Public%20PRIMO',
'issueCountry': 'ma'
},
'TlsFranceMarrakech_Case2': {
'code': 'maRAK2fr',
'country': 'fr',
'aptType': 'Grand%20Public%20VISE',
'issueCountry': 'ma'
},
'TlsFranceRabat_Case1': {
'code': 'maRBA2fr',
'country': 'fr',
'aptType': 'Primo',
'issueCountry': 'ma'
},
'TlsFranceRabat_Case2': {
'code': 'maRBA2fr',
'country': 'fr',
'aptType': 'Renouvellement',
'issueCountry': 'ma'
},
'TlsFranceAnnaba_Case1': {
'code': 'dzAAE2fr',
'country': 'fr',
'aptType': 'premiere_demande',
'issueCountry': 'dz'
},
'TlsFranceAnnaba_Case2': {
'code': 'dzAAE2fr',
'country': 'fr',
'aptType': 'Frequent',
'issueCountry': 'dz'
},
'TlsFranceAnnaba_Case3': {
'code': 'dzAAE2fr',
'country': 'fr',
'aptType': 'Circulation',
'issueCountry': 'dz'
},
};
let inj_html = `
<div id="textHunterTitle">TerminTracker| Hunter <span style="font-size:
14px;">v1.7</span></div>
<div id="ttHunterDiv">
<form id="ttHunterForm">
<select id="itemHunterList" name="centHunterList">
<option value="TlsFranceCasablanca_Case1">TLS France à Casablanca (cas
1)/MA</option>
<option value="TlsFranceCasablanca_Case2">TLS France à Casablanca (cas
2)/MA</option>
<option value="TlsFranceCasablanca_Case3">TLS France à Casablanca (cas
3)/MA</option>
<option value="TlsFranceRabat_Case1">TLS France à Rabat (cas
1)/MA</option>
<option value="TlsFranceRabat_Case2">TLS France à Rabat (cas
2)/MA</option>
<option value="TlsFranceFes_Case1">TLS France à Fès (cas 1)/MA</option>
<option value="TlsFranceFes_Case2">TLS France à Fès (cas 2)/MA</option>
<option value="TlsFranceOujda_Case1">TLS France à Oujda (cas
1)/MA</option>
<option value="TlsFranceOujda_Case2">TLS France à Oujda (cas
2)/MA</option>
<option value="TlsFranceTanger_Case1">TLS France à Tanger (cas
1)/MA</option>
<option value="TlsFranceAgadir_Case1">TLS France à Agadir (cas
1)/MA</option>
<option value="TlsFranceMarrakech_Case1">TLS France à Marrakech (cas
1)/MA</option>
<option value="TlsFranceMarrakech_Case2">TLS France à Marrakech (cas
2)/MA</option>
<option value="TlsGermanyRabat_Tourism">TLS Allemagne (tourisme) à
Rabat/MA</option>
<option value="TlsGermanyRabat_FamilyVisit">TLS Allemagne (visite
familiale) à Rabat/MA</option>
<option value="TlsFranceAnnaba_Case1">TLS France à Annaba (1ère
demande)/DZ</option>
<option value="TlsFranceAnnaba_Case2">TLS France à Annaba
(renouvellement ordinaire)/DZ</option>
<option value="TlsFranceAnnaba_Case3">TLS France à Annaba
(renouvellement circulation)/DZ</option>
</select>
<br>
<button id="selectHunterButton">Prendre un Rendez-Vous</button>
<br><br>
<label for="refreshHunterTime">Chercher chaque (secondes) :</label>
<input type="number" id="refreshHunterTime" name="refreshHunterTime"
value="300" required>
<br><br>
<div id="textHunterContainer">
<div id="statusT">Statut : </div>
<div id="messageZone">Prêt.</div>
</div>
</form>
</div>
<br>
<div id="linkHunter"><a href="https://www.termin-tracker-all.com"
target="_blank">www.termin-tracker-all.com</a></div>
`;
let inj_css = `
#messageZone {
text-align: center;
font-weight: bold;
font-size: 16px;
color: #336699;
display: inline-block;
}
#statusT {
text-align: center;
font-weight: bold;
font-size: 16px;
color: #336699;
display: inline-block;
}
label {
font-size: 16px;
color: #000000;
}
#textHunterContainer {
text-align: center;
}
#textHunterTitle {
color: #336699;
margin-top: 10px;
font-size: 22px;
text-align: center;
font-weight: bold;
}
#linkHunter {
color: #007bff;
text-decoration: none;
transition: color 0.3s ease;
font-size: 13px;
text-align: center;
}
#linkHunter:hover {
color: #0056b3;
text-decoration: underline;
font-size: 13px;
text-align: center;
}
button {
background-color: #336699;
color: #fff;
padding: 10px 20px;
font-size: 16px;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #214c7d;
}
select {
padding: 10px;
font-size: 16px;
border: none;
background-color: #fff;
border-radius: 5px;
margin: 5px;
}
#ttHunterDiv {
text-align: center;
}
`;
function alive_checker() {
console.log('T.T. Hunter alive.');
}
if (!is_booking_successful) {
var selectedSessionCenter = localStorage.getItem('selectedCenter');
if (selectedSessionCenter) {
await runExtension(true);
}
}
}
setInterval(alive_checker, 5000);
timer_interval_id = setInterval(keep_session_alive, 60*5*1000);
handleGUI();
}
function handleGUI() {
var itemList = document.getElementById('itemHunterList');
var selectedCenter = localStorage.getItem('selectedCenter');
if (selectedCenter) {
if (itemList) {
itemList.value = selectedCenter;
}
}
let button_elt = document.getElementById('selectHunterButton');
if (button_elt) {
button_elt.addEventListener('click', async function (event) {
// prevent page reload
event.preventDefault();
// main action
console.log('T.T. Hunter started operations..');
localStorage.setItem('selectedCenter', itemList.value);
await runExtension(true);
});
}
function padNumber(number) {
return number < 10 ? '0' + number : number;
}
function getTimestamp() {
let currentDate = new Date();
if (theGetResponse) {
if (theGetResponse.status === 200) {
var calendarTable = await theGetResponse.json();
console.log("calendarTable = ", calendarTable);
let validSlotsArr = getTheValidSlots(calendarTable);
let nbValidApts = validSlotsArr.length;
if (postResponse) {
if (postResponse.status === "success") {
is_booking_successful = true;
const endTimestamp = performance.now();
const elapsedTime = (endTimestamp -
startTimestamp)/1000.0;
console.log('POST request is successful !');
set_positive('Créneau [' + chosenDate + ' @ ' +
chosenTime + '] Réservé avec Succès. En: ' + elapsedTime.toFixed(2) + 's.' + ' | @
' + getTimestamp());
} else {
let errMsg = postResponse.status;
errMsg = errMsg.toString();
console.log('Erreur durant la requête POST.
Message du TLS: ' + errMsg);
set_error('Erreur durant la requête. Message du
TLS: ' + errMsg + ' | @ ' + getTimestamp());
}
} else {
console.log('Erreur durant la requête POST');
set_error('Erreur durant la requête.' + ' | @ ' +
getTimestamp());
}
} else {
const endTimestamp = performance.now();
const elapsedTime = (endTimestamp -
startTimestamp)/1000.0;
set_info('Pas de rendez-vous disponible. En: ' +
elapsedTime.toFixed(2) + 's | @ ' + getTimestamp());
}
} else {
const endTimestamp = performance.now();
const elapsedTime = (endTimestamp - startTimestamp)/1000.0;
set_info(nbValidApts.toString() + ' rendez-vous
disponible(s). En: ' + elapsedTime.toFixed(2) + 's | @ ' + getTimestamp());
}
} else {
let errMsg = '';
if (theGetResponse.status === 400) {
errMsg = 'Bad Request [400]';
} else if (theGetResponse.status === 401) {
errMsg = 'Unauthorized [401]';
} else if (theGetResponse.status === 403) {
errMsg = 'Forbidden [403]';
} else if (theGetResponse.status === 404) {
errMsg = 'Not Found [404]';
} else {
errMsg = theGetResponse.status;
}
errMsg = errMsg.toString();
console.log('Erreur durant la requête GET. Message du TLS: ' +
errMsg);
set_error('Erreur durant la requête. Message du TLS: ' + errMsg +
' | @ ' + getTimestamp());
}
} else {
console.log('Erreur durant la requête GET');
set_error('Erreur durant la requête.' + ' | @ ' +
getTimestamp());
}
}
console.log('T.T. Hunter finished.');
}
function set_warning(i_message) {
let messageZone = document.getElementById("messageZone");
messageZone.innerHTML = i_message;
messageZone.style.color = '#eb9e34';
}
function set_error(i_message) {
let messageZone = document.getElementById("messageZone");
messageZone.innerHTML = i_message;
messageZone.style.color = '#d1112e';
}
function set_positive(i_message) {
let messageZone = document.getElementById("messageZone");
messageZone.innerHTML = i_message;
messageZone.style.color = '#0b8f4d';
}
function set_info(i_message) {
let messageZone = document.getElementById("messageZone");
messageZone.innerHTML = i_message;
messageZone.style.color = '#336699';
}
function isMatchingUrl(url) {
const regex = /^https:\/\/fanyv88.com:443\/https\/visas-[a-zA-Z]{2}\.tlscontact\.com\/appointment\/[a-zA-
Z]{2}\/[a-zA-Z0-9]+\/\d+$/;
return regex.test(url);
}
function extractIdFromUrl(url) {
let regex = /\/(\d+)$/;
let match = url.match(regex);
function getCaptchaId() {
let captchaElts = document.getElementsByClassName('grecaptcha-logo')
if (captchaElts.length > 0) {
let urlCaptcha = captchaElts[0].getElementsByTagName('iframe')[0].src;
let urlParams = new URLSearchParams(urlCaptcha);
let captchaId = urlParams.get('k');
return captchaId;
}
return '';
}
function getTheValidSlots(inJsonData) {
let validSlots = [];
Object.keys(inJsonData).forEach(date => {
Object.keys(inJsonData[date]).forEach(time => {
if (inJsonData[date][time] === 1) {
validSlots.push({
date: date,
time: time
});
}
});
});
return validSlots;
}