US Certificate Digital Auto Authentication

Automatically clicks on the "Certificado digital" authentication button on Universidad de Sevilla login page

目前為 2025-04-11 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        US Certificate Digital Auto Authentication
// @name:es     Autenticacion con Certificado Digital Universidad de Sevilla
// @namespace   Violentmonkey Scripts
// @match       https://sso.us.es/*
// @grant       none
// @version     1.5
// @author      Alf
// @description Automatically clicks on the "Certificado digital" authentication button on Universidad de Sevilla login page
// @description:es Automaticamente clica en "Certificado digital" en la pagina de login de la Universidad de Sevilla
// @run-at      document-end
// @license     MIT
// ==/UserScript==

/* MIT License
 * 
 * Copyright (c) 2025 Alf
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

(function () {
	"use strict";

	// Track the current page URL to detect navigation
	let currentUrl = window.location.href;
	// Remember if we've acted on this specific page already
	let actedOnThisPage = false;

	// Function to check and handle the confirmation dialog
	function checkForConfirmationDialog() {
		// Skip if we've already acted on this page
		if (actedOnThisPage) {
			return false;
		}

		// Look for the confirmation dialog button with "Aceptar" text
		const confirmButton = document.querySelector(
			".ui-dialog-buttonset button span#submit_confirm"
		);

		if (
			confirmButton &&
			(confirmButton.textContent === "Aceptar" ||
				confirmButton.textContent.includes("Aceptar"))
		) {
			console.log('Confirmation dialog found, clicking "Aceptar"...');

			// Click the confirmation button
			confirmButton.closest("button").click();
			actedOnThisPage = true;

			// Clear any existing intervals
			if (window.checkIntervalId) {
				clearInterval(window.checkIntervalId);
				window.checkIntervalId = null;
			}

			return true;
		}

		return false;
	}

	// Main function to handle authentication
	function handleAuthentication() {
		// Reset our "acted" flag when URL changes (navigation or reload)
		if (currentUrl !== window.location.href) {
			currentUrl = window.location.href;
			actedOnThisPage = false;
			console.log("New page detected, ready to authenticate if needed");
		}

		// Skip if we've already acted on this page
		if (actedOnThisPage) {
			return;
		}

		// First check if we're already on the confirmation dialog
		if (checkForConfirmationDialog()) {
			return;
		}

		// If not, look for the certificate button
		const certButton = document.getElementById("x509_module");

		if (certButton) {
			console.log("Certificate digital button found, clicking...");
			certButton.click();
			actedOnThisPage = true;

			// Set up observer to detect when confirmation dialog appears
			const observer = new MutationObserver(function (mutations) {
				// Reset flag for confirmation dialog since it's a new element
				actedOnThisPage = false;

				for (const mutation of mutations) {
					if (mutation.addedNodes.length) {
						if (checkForConfirmationDialog()) {
							observer.disconnect();
							break;
						}
					}
				}
			});

			// Start observing the document for changes
			observer.observe(document.body, { childList: true, subtree: true });

			// Also set a fallback timer to check for the dialog (just once)
			setTimeout(function () {
				// Reset flag for confirmation dialog that might appear late
				actedOnThisPage = false;
				checkForConfirmationDialog();
			}, 1000);
		}
	}

	// Wait for page to fully load
	window.addEventListener("load", function () {
		// Short delay to ensure all elements are rendered
		setTimeout(handleAuthentication, 1000);
	});

	// Watch for URL changes (via History API)
	const originalPushState = history.pushState;
	history.pushState = function () {
		originalPushState.apply(this, arguments);
		actedOnThisPage = false;
		currentUrl = window.location.href;
	};

	const originalReplaceState = history.replaceState;
	history.replaceState = function () {
		originalReplaceState.apply(this, arguments);
		actedOnThisPage = false;
		currentUrl = window.location.href;
	};

	// Watch for URL changes (via navigation)
	window.addEventListener("popstate", function () {
		actedOnThisPage = false;
		currentUrl = window.location.href;
	});

	// Check once initially for dialog
	setTimeout(checkForConfirmationDialog, 500);

	// Short interval check for confirmation dialog
	// This will only run for a few seconds and will be cleared once a dialog is found
	window.checkIntervalId = setInterval(function () {
		if (!actedOnThisPage) {
			checkForConfirmationDialog();
		} else {
			clearInterval(window.checkIntervalId);
			window.checkIntervalId = null;
		}
	}, 1000);

	// Auto-clear interval after 5 seconds to prevent continuous checking
	setTimeout(function () {
		if (window.checkIntervalId) {
			clearInterval(window.checkIntervalId);
			window.checkIntervalId = null;
		}
	}, 5000);
})();