IDP - Auto Approve Stack

Automates environment selection, discards changes, and approves for specific environments.

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         IDP - Auto Approve Stack
// @namespace    http://tampermonkey.net/
// @version      2025-04-02
// @description  Automates environment selection, discards changes, and approves for specific environments.
// @match        https://*.cloudfront.net/*
// @grant        GM_log
// @run-at       document-idle
// @license MIT
// ==/UserScript==

(function () {
    'use strict';

    GM_log("Auto-Environment-Clicker script running...");

    const params = new URLSearchParams(window.location.search);
    const environment = params.get('environment');

    if (!environment) {
        console.warn("No 'environment' parameter found in the URL.");
        return;
    }


    GM_log(`Environment parameter found: ${environment}`);

    function notify(message) {
        const stackName = document.querySelector("body > app-root > div > stack-home > div > div:nth-child(1) > h1")
            .innerText.replace(" STACK", "").toLowerCase();

        // Get the current time in a human-readable format
        const currentTime = new Date().toLocaleString('en-US', {
            weekday: 'short', // Short day name
            year: 'numeric',
            month: 'short', // Short month name
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit',
            hour12: true // AM/PM format
        });

        // Format the message
        const m = `${currentTime}: ${message}`;

        // Send the message to the ntfy topic
        fetch('https://ntfy.sh/' + stackName, {
            method: 'POST',
            body: m
        })
            .then(response => {
                if (response.ok) {
                    GM_log(`Notification sent successfully: ${message}`);
                } else {
                    console.error('Failed to send notification.', response.statusText);
                }
            })
            .catch(error => {
                console.error('Error while sending notification:', error);
            });
    }

    function findAndClickEnvironmentSpan() {
        GM_log("running findAndClickEnvironmentSpan");
        const span = [...document.querySelectorAll('span.title')].find(el => el.textContent.trim().toLowerCase() === environment);
        const current_environment = document.querySelector("body > app-root > div > stack-home > div > div.card-container > div.environments > div").children[0].children[0].children[0].children[1].children[0].children[0].innerText.trim().toLowerCase()

        GM_log(current_environment, environment)

        if (current_environment == environment) {
            GM_log(`Skipping clicking on span as environment is already on ${environment}`)
            clearInterval(environmentCheckInterval);
            waitForApproveButton();
        }
        else if (span) {
            GM_log(`Found environment span: ${span.textContent}. Clicking it...`);
            span.click();
            clearInterval(environmentCheckInterval);
            // waitForDiscardDiaGM_log();
            waitForApproveButton();
        } else {
            GM_log(`Looking for span with environment name: ${environment}`);
        }
    }

    /*function waitForDiscardDiaGM_log() {
        GM_log("running waitForDiscardDialog")

        const discardCheckInterval = setInterval(() => {
            const yesButton = [...document.querySelectorAll('button')].find(btn => btn.textContent.trim() === 'Yes');

            if (yesButton) {
                GM_log("Found 'Yes' button in discard changes dialog. Clicking it...");
                yesButton.click();
                clearInterval(discardCheckInterval);
                waitForApproveButton();
            } else {
                GM_log("Looking for 'Yes' button in discard changes dialog...");
            }
        }, 1000);
    }*/

    function waitForApproveButton() {
        GM_log("running waitForApproveButton");

        const approveInterval = setInterval(() => {
            const approveButton = Array.from(document.querySelectorAll("button"))
                .find(button => button.textContent.trim().toUpperCase() === "APPROVE");

            if (approveButton) {
                GM_log("Found 'Approve' button. Clicking and stopping script...");
                approveButton.click();
                clearInterval(approveInterval);
                waitForOKButton();

                notify("APPROVED")

            } else {
                GM_log("Approve button not found yet ... waiting 1 sec");
            }
        }, 1000);
    }

    function waitForOKButton() {
        GM_log("running waitForOKButton");

        const okButtonInterval = setInterval(() => {
            const okButton = Array.from(document.querySelectorAll(".mat-focus-indicator.mat-stroked-button.mat-button-base.ng-star-inserted"))
                .find(button => button.innerText.trim() === "OK");

            if (okButton) {
                GM_log("Found 'OK' button. Clicking it...");
                okButton.click();
                clearInterval(okButtonInterval);
                waitForStackStatus();
            } else {
                GM_log("Looking for 'OK' button...");
            }
        }, 1000);
    }

    function waitForStackStatus() {
        GM_log("running waitForStackStatus");

        const stackStatusInterval = setInterval(() => {
            const stackStatusElement = document.querySelector(".mat-card-content.ng-star-inserted")?.children[0];
            const statusText = stackStatusElement ? stackStatusElement.innerText.trim() : "";

            if (statusText === "Stack Status: READY" || statusText === "Stack Status: FAILED") {
                GM_log(`Stack Status updated: ${statusText}. Stopping script.`);

                notify(statusText)


                clearInterval(stackStatusInterval);

                window.close();
            } else {
                GM_log(`Current Stack Status: ${statusText}. Waiting for it to change to READY or FAILED...`);
            }
        }, 1000);
    }

    const environmentCheckInterval = setInterval(findAndClickEnvironmentSpan, 1000);

})();