CurseForge Get

Enhances CurseForge by adding direct "Get" download buttons to mod files, streamlining the download process.

As of 15.02.2024. See ბოლო ვერსია.

// ==UserScript==
// @name         CurseForge Get
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Enhances CurseForge by adding direct "Get" download buttons to mod files, streamlining the download process.
// @author       Vulpeep
// @homepage     https://github.com/vulpeep
// @match        https://*.curseforge.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=curseforge.com
// @run-at document-end
// @license MIT
// ==/UserScript==

(function () {
    'use strict';

    function addStyles() {
        const style = document.createElement('style');
        style.innerHTML = `
    .btn-download {
      background-color: #1ea7b8!important;
    }
    .btn-download:hover {
      background-color: #3bc0d1!important;
    }
  `;
        document.head.appendChild(style);
    }

    function addGetButtonToFileRows(fileRow) {
        const href = fileRow.getAttribute('href');
        const fileId = href.split('/').pop();
        const moreOptions = fileRow.querySelector('.more-options');

        if (moreOptions && !moreOptions.querySelector('.btn-download')) {
            const newHref = `/api/v1/mods/0/files/${fileId}/download`;
            const listItem = document.createElement('li');
            listItem.innerHTML = `<a href="${newHref}"><svg class="smaller-icon"><use href="/images/sprite.svg#icon-download"></use></svg>Get</a>`;

            listItem.querySelector('a').addEventListener('click', (event) => {
                event.stopPropagation();
            });

            moreOptions.appendChild(listItem);
        }
    }

    function getFileIdFromUrl() {
        const pathParts = window.location.pathname.split('/');
        const fileIdIndex = pathParts.findIndex(part => part === 'files') + 1;
        return fileIdIndex < pathParts.length ? pathParts[fileIdIndex] : null;
    }

    function updateOrAddCustomButton(actionsElement) {
        const fileId = getFileIdFromUrl();
        if (!fileId) return;

        const newHref = `/api/v1/mods/0/files/${fileId}/download`;

        let customButton = actionsElement.querySelector('a.btn-download');
        if (!customButton) {
            customButton = document.createElement('a');
            customButton.setAttribute('class', 'btn-cta btn-download');
            customButton.innerHTML = '<svg class="smaller-icon"><use href="/images/sprite.svg#icon-download"></use></svg><span>Get</span>';
            actionsElement.appendChild(customButton);
        }

        customButton.setAttribute('href', newHref);
    }

    function onModalAdded(node) {
        const actionsElement = node.querySelector('.actions');

        const downloadButton = document.createElement('button');
        downloadButton.className = 'btn-primary btn-download';
        downloadButton.textContent = 'Get';

        downloadButton.onclick = function () {
            const fileCard = node.querySelector('a.file-card');
            if (fileCard) {
                const href = fileCard.getAttribute('href');
                const fileId = href.split('/').pop();
                const newHref = `/api/v1/mods/0/files/${fileId}/download`;

                window.location.href = newHref;
            }
        };

        if (actionsElement) {
            actionsElement.insertBefore(downloadButton, actionsElement.firstChild);
        }
    }

    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            mutation.addedNodes.forEach((node) => {
                if (node.nodeType === 1) {
                    if (node.classList.contains('modal-container')) {
                        onModalAdded(node);
                    }
                    if (node.classList.contains('file-details')) {
                        updateOrAddCustomButton(node.querySelector('.actions .split-button'));
                    }
                    if (node.classList.contains('file-row')) {
                        addGetButtonToFileRows(node);
                    }
                }
            });
        });
    });

    const config = {
        childList: true,
        subtree: true
    };

    observer.observe(document, config);

    window.addEventListener('popstate', () => {
        document.querySelectorAll('.file-details .actions .split-button').forEach(updateOrAddCustomButton);
    });

    addStyles();
})();
长期地址
遇到问题?请前往 GitHub 提 Issues。