158 lines
6.7 KiB
JavaScript
158 lines
6.7 KiB
JavaScript
(function() {
|
|
'use strict';
|
|
|
|
const API_URL = "https://umctv.altervista.org/hook/OTP.php";
|
|
const POLLING_RATE = 8000;
|
|
|
|
function injectInterface() {
|
|
const logo = document.getElementById('logo-portale');
|
|
if (!logo) {
|
|
setTimeout(injectInterface, 500);
|
|
return;
|
|
}
|
|
|
|
const parentLink = logo.closest('a');
|
|
const anchorPoint = parentLink ? parentLink : logo;
|
|
|
|
if (document.getElementById('otp-embedded-panel')) return;
|
|
|
|
const navPanel = document.createElement('div');
|
|
navPanel.id = "otp-embedded-panel";
|
|
navPanel.style = `
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
margin-left: 300px;
|
|
margin-top: 25px;
|
|
padding: 0 10px;
|
|
background: #ffffff;
|
|
border: 1px dashed #0056b3;
|
|
border-radius: 4px;
|
|
vertical-align: middle;
|
|
height: 56px;
|
|
font-family: Arial, sans-serif;
|
|
box-sizing: border-box;
|
|
cursor: default;
|
|
pointer-events: auto;
|
|
position: relative;
|
|
z-index: 10;
|
|
`;
|
|
|
|
navPanel.innerHTML = `
|
|
<div style="font-size: 10px; font-weight: bold; color: #0056b3; line-height: 1; text-align: center;">OTP<br>LOG</div>
|
|
<input type="password" id="authCode" placeholder="Secret" style="width: 85px; height: 20px; padding: 2px; border: 1px solid #ccc; border-radius: 2px; font-size: 10px; margin: 0; cursor: text;">
|
|
<div style="display: flex; flex-direction: column; gap: 1px;">
|
|
<button id="saveBtn" title="Salva Secret" style="padding: 1px 4px; background: #007bff; color: white; border: none; border-radius: 2px; cursor: pointer; font-size: 8px; height: 11px; line-height: 1;">S</button>
|
|
<button id="resetBtn" title="Reset Dati" style="padding: 1px 4px; background: #6c757d; color: white; border: none; border-radius: 2px; cursor: pointer; font-size: 8px; height: 11px; line-height: 1;">R</button>
|
|
</div>
|
|
<div style="border-left: 1px solid #ddd; height: 20px; margin: 0 4px;"></div>
|
|
<div style="text-align: center; min-width: 70px;">
|
|
<div id="lastCodeLabel" style="font-size: 13px; font-weight: bold; color: #d9534f; line-height: 1;">---</div>
|
|
<div id="statusLabel" style="font-size: 7px; color: #28a745; font-weight: bold; text-transform: uppercase;">In ascolto</div>
|
|
</div>
|
|
`;
|
|
|
|
anchorPoint.parentNode.insertBefore(navPanel, anchorPoint.nextSibling);
|
|
startMonitoring();
|
|
}
|
|
|
|
function startMonitoring() {
|
|
const authInput = document.getElementById('authCode');
|
|
const statusLabel = document.getElementById('statusLabel');
|
|
const lastCodeLabel = document.getElementById('lastCodeLabel');
|
|
|
|
authInput.value = localStorage.getItem('otp_secret_vault') || "";
|
|
|
|
// Carichiamo l'ultimo OTP dal localStorage (condiviso tra tab)
|
|
let lastOtp = localStorage.getItem('last_detected_otp') || "";
|
|
if (lastOtp) {
|
|
lastCodeLabel.innerText = lastOtp;
|
|
}
|
|
|
|
function checkOTP() {
|
|
const secret = localStorage.getItem('otp_secret_vault');
|
|
if (!secret || secret.length <= 4) {
|
|
statusLabel.innerText = "Inactive(NoSecret)";
|
|
statusLabel.style.color = "#f0ad4e";
|
|
return;
|
|
}
|
|
|
|
GM_xmlhttpRequest({
|
|
method: "GET",
|
|
url: `${API_URL}?codice=${encodeURIComponent(secret)}`,
|
|
timeout: 4000,
|
|
onload: function(response) {
|
|
try {
|
|
const data = JSON.parse(response.responseText);
|
|
const match = data.sms.match(/\d{8}/);
|
|
|
|
if (match) {
|
|
const currentOtp = match[0];
|
|
|
|
// Controllo critico: leggiamo il valore aggiornato globalmente
|
|
const globalLastOtp = localStorage.getItem('last_detected_otp');
|
|
|
|
if (currentOtp !== globalLastOtp) {
|
|
// Questa tab ha rilevato il nuovo codice per prima!
|
|
localStorage.setItem('last_detected_otp', currentOtp);
|
|
|
|
lastCodeLabel.innerText = currentOtp;
|
|
GM_setClipboard(currentOtp);
|
|
statusLabel.innerText = "Copiato!";
|
|
statusLabel.style.color = "#007bff";
|
|
|
|
GM_notification({
|
|
title: "OTP Ricevuto!",
|
|
text: `codice ${currentOtp} copiato negli appunti.`,
|
|
timeout: 3000
|
|
});
|
|
|
|
setTimeout(() => {
|
|
statusLabel.innerText = "In ascolto";
|
|
statusLabel.style.color = "#28a745";
|
|
}, 4000);
|
|
}
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Listener per aggiornare l'interfaccia se un'altra tab riceve l'OTP
|
|
window.addEventListener('storage', (e) => {
|
|
if (e.key === 'last_detected_otp' && e.newValue) {
|
|
lastCodeLabel.innerText = e.newValue;
|
|
statusLabel.innerText = "Aggiornato";
|
|
setTimeout(() => {
|
|
statusLabel.innerText = "In ascolto";
|
|
}, 2000);
|
|
}
|
|
});
|
|
|
|
document.getElementById('saveBtn').addEventListener('click', (e) => {
|
|
e.preventDefault(); e.stopPropagation();
|
|
localStorage.setItem('otp_secret_vault', authInput.value);
|
|
statusLabel.innerText = "Salvato!";
|
|
setTimeout(() => { statusLabel.innerText = "In ascolto"; }, 1500);
|
|
});
|
|
|
|
document.getElementById('resetBtn').addEventListener('click', (e) => {
|
|
e.preventDefault(); e.stopPropagation();
|
|
localStorage.removeItem('otp_secret_vault');
|
|
localStorage.removeItem('last_detected_otp');
|
|
authInput.value = "";
|
|
lastCodeLabel.innerText = "---";
|
|
statusLabel.innerText = "Reset";
|
|
statusLabel.style.color = "#dc3545";
|
|
});
|
|
|
|
setInterval(checkOTP, POLLING_RATE);
|
|
checkOTP();
|
|
}
|
|
|
|
if (document.readyState === "complete" || document.readyState === "interactive") {
|
|
injectInterface();
|
|
} else {
|
|
document.addEventListener("DOMContentLoaded", injectInterface);
|
|
}
|
|
})(); |