Greasy Fork

Greasy Fork is available in English.

GGn Group Expansion

Adds quick buttons for expanding all groups and filelist on GGn pages.

目前为 2025-04-28 提交的版本,查看 最新版本

// ==UserScript==
// @name         GGn Group Expansion
// @version      1.2.1
// @author       SleepingGiant
// @description  Adds quick buttons for expanding all groups and filelist on GGn pages.
// @namespace    http://greasyfork.icu/users/1395131
// @match        https://gazellegames.net/torrents.php?id=*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';
    console.log('[GGn Script] Script started.');

    function ensureVerticalCornerContainer() {
        console.log('[ensureVerticalCornerContainer] Called.');
        let container = document.getElementById('vertical-corner-container');
        console.log('[ensureVerticalCornerContainer] container:', container);

        if (!container) {
            console.log('[ensureVerticalCornerContainer] container not found. Creating new.');
            container = document.createElement('div');
            container.id = 'vertical-corner-container';
            container.style.position = 'absolute'; // match Multi Reporter
            document.body.appendChild(container);
            console.log('[ensureVerticalCornerContainer] container created and appended.');

            const groupDetails = document.getElementById('content');
            console.log('[ensureVerticalCornerContainer] groupDetails:', groupDetails);

            if (groupDetails) {
                container.style.left = (groupDetails.offsetLeft + groupDetails.offsetWidth) + 'px';
                container.style.top = groupDetails.offsetTop + 'px';
                console.log(`[ensureVerticalCornerContainer] container positioned at left: ${container.style.left}, top: ${container.style.top}`);
            }
        }
        return container;
    }

    function insertExpandAllButton() {
        console.log('[insertExpandAllButton] Called.');
        const container = ensureVerticalCornerContainer();
        console.log('[insertExpandAllButton] container:', container);

        const expandButton = document.createElement('button');
        expandButton.textContent = 'Expand All';
        expandButton.type = 'button';
        expandButton.style.writingMode = 'vertical-lr';
        expandButton.style.height = 'unset';
        expandButton.style.margin = '4px 0';
        expandButton.id = 'expand-all-button';
        expandButton.onclick = () => {
            console.log('[expand-all-button] Clicked.');
            expandAll();
        };
        container.appendChild(expandButton);
        console.log('[insertExpandAllButton] expandButton created and appended.');
    }

    function insertInlineEditionButtons() {
        console.log('[insertInlineEditionButtons] Called.');
        const editions = document.querySelectorAll('.edition_info');
        console.log(`[insertInlineEditionButtons] Found ${editions.length} editions.`);

        editions.forEach((edition, index) => {
            console.log(`[insertInlineEditionButtons] Processing edition ${index}:`, edition);
            const btn = document.createElement('button');
            btn.textContent = 'Expand Edition';
            btn.style.marginLeft = '10px';
            btn.type = 'button';
            btn.classList.add('expand-edition-button');
            btn.onclick = (e) => {
                console.log('[expand-edition-button] Clicked.', edition);
                e.stopPropagation(); // Don't trigger edition row collapse toggle
                expandSingleEdition(edition);
            };
            edition.appendChild(btn);
            console.log('[insertInlineEditionButtons] Button appended to edition.');
        });
    }

    function sleep(ms) {
        console.log(`[sleep] Sleeping for ${ms} milliseconds.`);
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    function expandAll() {
        console.log('[expandAll] Called.');

        document.querySelectorAll('.edition_info').forEach((edition, index) => {
            console.log(`[expandAll] Expanding edition ${index}:`, edition);
            const editionIdMatch = edition.getAttribute('onclick')?.match(/#edition_(\d+)/);
            console.log(`[expandAll] editionIdMatch:`, editionIdMatch);

            if (editionIdMatch) {
                const tbody = document.getElementById(`edition_${editionIdMatch[1]}`);
                console.log(`[expandAll] tbody:`, tbody);

                if (tbody && tbody.style.display === 'none') {
                    console.log(`[expandAll] Clicking edition to expand.`);
                    edition.click();
                }
            }
        });

        document.querySelectorAll('a[onclick*="torrent_"]').forEach((a, index) => {
            console.log(`[expandAll] Expanding torrent link ${index}:`, a);
            const torrentIdMatch = a.getAttribute('onclick')?.match(/#torrent_(\d+)/);
            console.log(`[expandAll] torrentIdMatch:`, torrentIdMatch);

            if (torrentIdMatch) {
                const torrentId = torrentIdMatch[1];
                console.log(`[expandAll] torrentId:`, torrentId);
                const torrentRow = document.getElementById(`torrent_${torrentId}`);
                console.log(`[expandAll] torrentRow:`, torrentRow);

                if (torrentRow && torrentRow.classList.contains('hidden')) {
                    console.log(`[expandAll] Toggling torrent row.`);
                    jQuery(`#torrent_${torrentId}`).toggle();
                }
            }
        });

        document.querySelectorAll('a[onclick^="show_files"]').forEach((a, index) => {
            console.log(`[expandAll] Expanding file link ${index}:`, a);
            const fileId = a.getAttribute('onclick')?.match(/\d+/)?.[0];
            console.log(`[expandAll] fileId:`, fileId);

            if (fileId) {
                const filesDiv = document.getElementById(`files_${fileId}`);
                console.log(`[expandAll] filesDiv:`, filesDiv);

                if (filesDiv && filesDiv.classList.contains('hidden')) {
                    console.log(`[expandAll] Showing files.`);
                    show_files(fileId);
                }
            }
        });
    }

    function expandSingleEdition(edition) {
        console.log('[expandSingleEdition] Called for edition:', edition);

        const editionIdMatch = edition.getAttribute('onclick')?.match(/#edition_(\d+)/);
        console.log('[expandSingleEdition] editionIdMatch:', editionIdMatch);

        if (editionIdMatch) {
            const editionId = editionIdMatch[1];
            console.log('[expandSingleEdition] editionId:', editionId);

            const tbody = document.getElementById(`edition_${editionId}`);
            console.log('[expandSingleEdition] tbody:', tbody);

            if (tbody && tbody.style.display === 'none') {
                console.log('[expandSingleEdition] Clicking edition to expand.');
                edition.click();
            }

            if (tbody) {
                tbody.querySelectorAll('a[onclick*="torrent_"]').forEach((a, index) => {
                    console.log(`[expandSingleEdition] Expanding torrent ${index} in edition:`, a);
                    const torrentIdMatch = a.getAttribute('onclick')?.match(/#torrent_(\d+)/);
                    console.log(`[expandSingleEdition] torrentIdMatch:`, torrentIdMatch);

                    if (torrentIdMatch) {
                        const torrentId = torrentIdMatch[1];
                        console.log('[expandSingleEdition] torrentId:', torrentId);

                        const torrentRow = document.getElementById(`torrent_${torrentId}`);
                        console.log('[expandSingleEdition] torrentRow:', torrentRow);

                        if (torrentRow && torrentRow.classList.contains('hidden')) {
                            console.log('[expandSingleEdition] Toggling torrent row.');
                            jQuery(`#torrent_${torrentId}`).toggle();
                        }
                    }
                });

                tbody.querySelectorAll('a[onclick^="show_files"]').forEach((a, index) => {
                    console.log(`[expandSingleEdition] Expanding file ${index} in edition:`, a);
                    const fileId = a.getAttribute('onclick')?.match(/\d+/)?.[0];
                    console.log('[expandSingleEdition] fileId:', fileId);

                    if (fileId) {
                        const filesDiv = document.getElementById(`files_${fileId}`);
                        console.log('[expandSingleEdition] filesDiv:', filesDiv);

                        if (filesDiv && filesDiv.classList.contains('hidden')) {
                            console.log('[expandSingleEdition] Showing files.');
                            show_files(fileId);
                        }
                    }
                });
            }
        }
    }

    const loader = setInterval(() => {
        console.log('[loader] Checking if buttons already exist.');
        if (document.getElementById('expand-all-button') || document.querySelector('.expand-edition-button')) {
            console.log('[loader] Buttons found, clearing interval.');
            clearInterval(loader);
        } else {
            console.log('[loader] Buttons not found, inserting.');
            insertExpandAllButton();
            insertInlineEditionButtons();
        }
    }, 200);

})();