GitHub Repository Downloader

Download GitHub repositories directly from user profile page

Per 10-04-2025. Zie de nieuwste versie.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         GitHub Repository Downloader
// @namespace    Violentmonkey Scripts
// @version      2.0
// @description  Download GitHub repositories directly from user profile page
// @author       You
// @match        https://github.com/*?tab=repositories
// @grant        GM_registerMenuCommand
// @grant        GM_download
// @run-at      document-end
// @license MIT
// @require      https://update.greasyfork.org/scripts/530526/1558038/ProgressUI-Module.js
// ==/UserScript==

(function() {
    'use strict';

    function extractBaseUrl(urlString = location.href) {
        const urlObj = new URL(urlString);
        return `${urlObj.origin}${urlObj.pathname.split("/").slice(0, 2).join("/")}`;
    }

    function extractRepoData() {
        const ulElement = document.querySelector('ul[data-filterable-for="your-repos-filter"][data-filterable-type="substring"]');
        if (!ulElement){
            alert("ulElement not found!!")
            return
        }
        
        const liElements = ulElement.querySelectorAll("li");
        const liArray = Array.from(liElements);
        
        return liArray.map(li => {
            const repoLink = li.querySelector('a[itemprop="name codeRepository"]');
            if (!repoLink) return null;
            const repository = repoLink.href;

            const name = repoLink.textContent.trim();

            const language = li.querySelector('span[itemprop="programmingLanguage"]')?.textContent.trim();

            const lastUpdated = li.querySelector("relative-time")?.getAttribute("datetime");

            const isPublic = li.querySelector(".Label.Label--secondary")?.textContent.trim() === "Public";
            
            const downloadLinks = [
                `${repository}/archive/refs/heads/master.zip`,
                `${repository}/archive/refs/heads/main.zip`
            ];
            
            return {
                name,
                language,
                lastUpdated,
                isPublic,
                repository,
                downloadLinks
            };
        }).filter(Boolean);
    }

    function downloadRepos() {
        const repos = extractRepoData();
        if (repos.length === 0) {
            ProgressUI.showQuick('No repositories found on this page', { 
                percent: 100, 
                theme: 'dark',
                duration: 3000
            });
            return;
        }

        const progress = new ProgressUI({
            position: 'bottom-right',
            theme: 'dark',
            title: 'GitHub Repository Downloader',
            closable: true,
            width: '350px',
        });

        let downloadedCount = 0;
        let failedCount = 0;
        const totalCount = repos.length;

        progress.update(`Starting download of ${totalCount} repositories...`, 0);

        repos.forEach((repo, index) => {
            const mainZipUrl = repo.downloadLinks[1];
            const masterZipUrl = repo.downloadLinks[0];
            
            setTimeout(() => {
                progress.update(`Downloading ${repo.name} (${index + 1}/${totalCount})...`, (index / totalCount) * 100);
                
                GM_download({
                    url: mainZipUrl,
                    name: `${repo.name}-main.zip`,
                    onload: () => {
                        downloadedCount++;
                        updateProgressStatus(progress, downloadedCount, failedCount, totalCount);
                    },
                    onerror: () => {
                        progress.update(`Trying master branch for ${repo.name}...`, (index / totalCount) * 100);
                        
                        GM_download({
                            url: masterZipUrl,
                            name: `${repo.name}-master.zip`,
                            onload: () => {
                                downloadedCount++;
                                updateProgressStatus(progress, downloadedCount, failedCount, totalCount);
                            },
                            onerror: () => {
                                failedCount++;
                                progress.update(`Failed to download ${repo.name}`, (index / totalCount) * 100);
                                updateProgressStatus(progress, downloadedCount, failedCount, totalCount);
                            }
                        });
                    }
                });
            }, index * 1000);
        });
    }

    function updateProgressStatus(progress, downloaded, failed, total) {
        const completed = downloaded + failed;
        const percent = Math.round((completed / total) * 100);
        
        if (completed === total) {
            if (failed === 0) {
                progress.update(`All ${total} repositories downloaded successfully!`, 100);
            } else {
                progress.update(`Download completed: ${downloaded} successful, ${failed} failed`, 100);
            }
            progress.scheduleCleanup(5000);
        } else {
            progress.update(`Downloaded: ${downloaded}, Failed: ${failed}, Remaining: ${total - completed}`, percent);
        }
    }

    GM_registerMenuCommand("Download GitHub Repositories", downloadRepos);
})();