// ==UserScript==
// @name OTP NTFY Console (Token)
// @namespace http://tampermonkey.net/
// @version 2.1
// @description Pannello OTP sicuro con Bearer Token e monitoraggio live
// @author Gemini + Gatto
// @match *://www.ilportaledellautomobilista.it/*
// @grant GM_notification
// @grant GM_setClipboard
// ==/UserScript==
(function() {
'use strict';
// --- CONFIGURAZIONE SICURA ---
const BASE_URL = "ntfy.dati-web.it";
// <--- INCOLLA QUI IL TUO TOKEN tk_...
const NTFY_TOKEN = "tk_mh1ox5scgkorten10a7baelpehh6p";
let currentTopic = localStorage.getItem('otp_topic') || "OTP-Gatto";
let mode = localStorage.getItem('otp_gatto_mode') || "notify";
const OTP_REGEX = /(?:^|\s)(\S{8})(?=\s|$)/;
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";
// Stile del pannello
navPanel.style = `
display: inline-flex;
align-items: center;
gap: 12px;
margin-left: 300px;
margin-top: 16px;
padding: 0 15px;
background: #f8f9fa;
border: 2px solid #0056b3;
border-radius: 8px;
height: 60px;
min-width: 320px;
font-family: 'Segoe UI', Arial, sans-serif;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
z-index: 9999;
`;
navPanel.innerHTML = `
`;
anchorPoint.parentNode.insertBefore(navPanel, anchorPoint.nextSibling);
// Salvataggio impostazioni
document.getElementById('saveConfig').addEventListener('click', () => {
localStorage.setItem('otp_topic', document.getElementById('topicInput').value.trim());
localStorage.setItem('otp_gatto_mode', document.querySelector('input[name="otpMode"]:checked').value);
location.reload();
});
startListening();
}
async function startListening() {
const statusLabel = document.getElementById('statusLabel');
try {
const response = await fetch(`https://${BASE_URL}/${currentTopic}/json`, {
headers: {
"Authorization": `Bearer ${NTFY_TOKEN}`
}
});
if (response.status === 401 || response.status === 403) {
statusLabel.innerText = "ERRORE TOKEN";
statusLabel.style.color = "red";
return;
}
if (!response.ok) throw new Error("Errore connessione");
statusLabel.innerText = "ONLINE";
statusLabel.style.color = "#28a745";
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { value, done } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (!line.trim()) continue;
try {
const data = JSON.parse(line);
if (data.event === 'message' && data.message) {
const match = data.message.match(OTP_REGEX);
if (match) handleOTP(match[1]);
}
} catch (e) { console.error("Errore parsing JSON", e); }
}
}
} catch (err) {
statusLabel.innerText = "RE-CONNECTING...";
statusLabel.style.color = "orange";
setTimeout(startListening, 5000);
}
}
function handleOTP(newOtp) {
document.getElementById('lastCodeLabel').innerText = newOtp;
GM_setClipboard(newOtp);
// Notifica di sistema
GM_notification({
title: "OTP Infocert",
text: `Codice: ${newOtp} (Copiato)`,
timeout: 5000
});
// Se la modalità è "Digita", prova a inserirlo nel primo campo input vuoto trovato
if (document.querySelector('input[name="otpMode"]:checked').value === 'type') {
const otpInput = document.querySelector('input[type="text"], input[maxlength="8"]');
if (otpInput) {
otpInput.value = newOtp;
otpInput.dispatchEvent(new Event('input', { bubbles: true }));
}
}
}
if (document.readyState === "complete" || document.readyState === "interactive") {
injectInterface();
} else {
document.addEventListener("DOMContentLoaded", injectInterface);
}
})();