Aggiunti file javascript
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
// ==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 = `
|
||||
<div style="display: flex; flex-direction: column; gap: 4px;">
|
||||
<input type="text" id="topicInput" value="${currentTopic}" placeholder="Topic" style="width: 100px; height: 20px; font-size: 11px; border: 1px solid #ccc; border-radius: 3px; padding: 2px 5px;">
|
||||
<button id="saveConfig" style="width: 110px; height: 22px; font-size: 10px; background: #0056b3; color: white; border: none; border-radius: 3px; cursor: pointer; font-weight: bold;">AGG. TOPIC</button>
|
||||
</div>
|
||||
|
||||
<div style="border-left: 1px solid #ccc; height: 40px;"></div>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: #333;">
|
||||
<label style="cursor:pointer; display: flex; align-items: center; gap: 5px;">
|
||||
<input type="radio" name="otpMode" value="notify" ${mode==='notify'?'checked':''}> Notifica
|
||||
</label>
|
||||
<label style="cursor:pointer; display: flex; align-items: center; gap: 5px;">
|
||||
<input type="radio" name="otpMode" value="type" ${mode==='type'?'checked':''}> Digita
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div style="border-left: 1px solid #ccc; height: 40px;"></div>
|
||||
|
||||
<div style="text-align: center; flex-grow: 1;">
|
||||
<div id="lastCodeLabel" style="font-size: 18px; font-weight: bold; color: #d9534f; letter-spacing: 1px;">---</div>
|
||||
<div id="statusLabel" style="font-size: 9px; color: #28a745; font-weight: bold;">STABILE</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
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);
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user