您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically clicks on the "Certificado digital" authentication button on Universidad de Sevilla login page
- // ==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);
- })();