Greasy Fork

atlassian license bulk copy

Inserts a textarea with basic license info in csv format for easy export

目前为 2025-03-14 提交的版本。查看 最新版本

// ==UserScript==
// @name         atlassian license bulk copy
// @namespace    http://tampermonkey.net/
// @version      2025.03.14.1
// @description  Inserts a textarea with basic license info in csv format for easy export
// @author       gwelch-contegix
// @match        https://my.atlassian.com/product
// @match        https://my.atlassian.com/products/*
// @match        https://www.atlassian.com/purchase/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=atlassian.com
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    "use strict"
    window.addEventListener("load", (event) => {
        function printlicense(n) {
            let lic = n.nextElementSibling
            console.log("printing", n.childNodes[1].textContent.trim().replaceAll(",", ""));
            if (
                lic.querySelector("*[data-cy=mac-expanded-account-name] span") == null ||
                lic.querySelector("*[data-cy=mac-sen-details]") == null
            ) {
                console.log("Elements not found:", lic.querySelector("*[data-cy=mac-expanded-account-name] span"), lic.querySelector("textarea"), lic.querySelector("*[data-cy=mac-sen-details]"));
                setTimeout(printlicense, 1000, n)
                return
            }
            function getLicenseCountAndPluginName(name) {
                let split_name = name.split(" ")
                let data = split_name.indexOf("(Data")
                var app_name = ""
                if (split_name[data + 1] == "Center)") {
                    let plugin = split_name.lastIndexOf("for", data)
                    if (plugin < 0) {
                        app_name = split_name.slice(0, data).join(" ")
                    } else {
                        app_name = split_name[plugin + 1]
                    }
                }
                var license_count_index = split_name.lastIndexOf("Users:") - 1
                var license_count = ""
                if (license_count_index > 0) {
                    license_count = split_name.at(license_count_index)
                } else {
                    license_count_index = split_name.lastIndexOf("Agents:") - 1
                    if (license_count_index > 0) {
                        license_count = split_name.at(license_count_index)
                        if (license_count == "Remote") {
                            license_count = split_name.at(license_count_index - 1)
                        }
                    }
                }
                return [app_name, license_count]
            }
            let sen = lic.querySelector("*[data-cy=mac-sen-details] > div > span").textContent.trim().replaceAll(",", "")
            let org = lic
                .querySelector("*[data-cy=mac-expanded-account-name] > div > span").childNodes[0]
                .textContent.trim()
                .replaceAll(",", "")
            let name = n
                .childNodes[1]
                .textContent.trim()
                .replaceAll(",", "")

            let expiry = n
                .querySelector(`*[data-cy=license-collapsed-row-expiration-date-${sen.slice(4)}]`)
                .textContent.trim()
                .replaceAll(",", "")
            var product_key = "";
            var license = "";
            if (name.indexOf('Cloud') == -1) {
                let url = new URL(lic.querySelector(`*[data-cy="actions-section-upgrade-button"]`).getAttribute('href'));
                product_key = url.searchParams.get('productKey');
                license = lic
                    .querySelector("textarea")
                    .value.trim()
                    .replaceAll(",", "");
            }
            if (product_key.endsWith(".data-center")) {
                product_key = product_key.slice(0, -12)
            }
            let [app_name, license_count] = getLicenseCountAndPluginName(name)
            let line =
                `${license_count},${org},${name},${app_name},${product_key},${expiry},${sen},${license}`.replaceAll(
                    "\n",
                    "",
                )
            document.getElementById("tsx-csv").value += line + "\n"
            console.log(line)
            window.TSX_license_count -= 1
        }
        function notify(message, time) {
            var popup = document.createElement('div');
            popup.innerText = message;
            var cssText = '';
            cssText += 'position: "fixed";';
            cssText += 'bottom: "0%";';
            cssText += 'right: "0%";';
            cssText += 'background-color: "red";';
            cssText += 'padding: "10px";';
            cssText += 'border: "1px solid black";';
            cssText += 'z-index: "1000";';
            popup.style.cssText = cssText;
            document.body.appendChild(popup)

            // Hide the popup after a delay (e.g., 3 seconds)
            setTimeout(function () {
                popup.remove();
            }, time)
        }
        function licenseDone() {
            if (window.TSX_license_count > 0) {
                console.log("waiting for csv to complete " + window.TSX_license_count)
                notify(
                    "waiting for csv to complete " + window.TSX_license_count + " left",
                    1050,
                )
                setTimeout(licenseDone, 1000)
                return
            }
            console.log("csv is done")
            notify("csv is done", 5000)
            let d = document.getElementById("tsx-div")
            let p = document.createElement("p")
            p.textContent = "csv is done"
            d.appendChild(p)
        }
        function click(n) {
            n.querySelector("span").click()
        }
        function download(file, text) {
            let element = document.createElement("a")
            element.setAttribute(
                "href",
                "data:text/plain;charset=utf-8," + encodeURIComponent(text),
            )
            element.setAttribute("download", file)
            document.body.appendChild(element)
            element.click()

            document.body.removeChild(element)
        }
        function getlicenses() {
            var wait = 0
            for (let name of document
                .querySelectorAll(
                    "tr:has(td.LicensesCollapsedRow__Cell-sc-1hqm79z-0)",
                )
                .values()
                .toArray()
                .reverse()) {
                if (name.checkVisibility()) {
                    window.TSX_license_count += 1
                    if (window.TSX_license_count % 2 == 0) {
                        wait += 1000
                    }
                    setTimeout(click, 1200 * window.TSX_license_count, name)
                    printlicense(name)
                }
            }
            licenseDone()
        }
        function installForm() {
            let form = document.querySelector(
                "div.styledComponents__StyledLinksWrapper-sc-balsup-29:has(> button)",
            )
            console.log(form);
            let div = document.createElement("div")
            div.id = "tsx-div"
            let csv = document.createElement("textarea")
            let btnGetLicenses = document.createElement("button")
            let btnDownloadCSV = document.createElement("button")
            csv.id = "tsx-csv"
            csv.value = "license_count,owner,app,app_name,product_key,expiry,sen,license\n"
            csv.style.cssText='display: "block";width: "100%";'
            div.style.cssText='margin: "0px 6px 0 0";'
            btnGetLicenses.textContent = "Get Licenses"
            btnGetLicenses.addEventListener("click", getlicenses)
            btnDownloadCSV.textContent = "download csv"
            btnDownloadCSV.addEventListener("click", function (e) {
                download("licenses.csv", csv.value)
            })
            div.appendChild(csv)
            div.appendChild(btnGetLicenses)
            div.appendChild(btnDownloadCSV)
            form.after(div)
            window.TSX_license_count = 0
        }
        function wait_for_load(mutationList, observer) {
            var foundNode = null;
            var target = null;
            for (const mutation of mutationList) {
                for (var node of mutation.addedNodes) {
                    if (node.querySelector('div.styledComponents__StyledLinksWrapper-sc-balsup-29:has(> button)') != null) {
                        foundNode = node;
                        target = mutation.target;
                    }
                }
            }

            if (foundNode == null) {
                return;
            }
            installForm();
        }
        let sd_init_observer = new MutationObserver(wait_for_load);
        sd_init_observer.observe(document.body, {childList: true, subtree:true});
    })
})()