GitHubReleasesCount

To show download counter for each attachment from Releases page on GitHub.com

// ==UserScript==
// @name        GitHubReleasesCount
// @description To show download counter for each attachment from Releases page on GitHub.com
// @namespace   net.r_eg.GitHubReleasesCount
// @version     0.4
// @grant       none
// @include     https://github.com/*/*/releases*
// @require     https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
// @author      https://github.com/3F
// @license     MIT
// ==/UserScript==

/* 
 Here's sandbox as the main page of this script at this time:
 - https://github.com/3F/sandbox/tree/master/javascript/_user_scripts/GitHubReleasesCount
 
 Tested via: 
    - Firefox 61.0.2 + Greasemonkey 4.6
    - Firefox 59.0.2 + Greasemonkey 4.3
    - Firefox 55.0.3 & 54.0.1 + Greasemonkey 3.11
    
 Changes:
     * 0.4: Fixed the work with modern GitHub Releases ~ Aug 2018
     * 0.3: Fixed the work with modern GitHub Releases ~(Jan 2018 - Apr 2018)
     * 0.2: individual tags & multi-pages support (+async).
     * 0.1: first idea.
*/
(function()
{
    'use strict';

    class GhrCounter extends function(){ this.constructor.prototype.$ =
    {
        /** assets from the releases page */
        pageFiles: ".release-header + :first-of-type li a",

        /** 'user/project' from url */
        usrprj: /^\/([^/]+)\/([^/]+)/g,

        apiserver: 'api.github.com',

        out: {
            class: 'Label Label--outline Label--outline-green text-gray',
            style: 'margin-right: 3px;',
        },

        debug: false,

        /* --------------- */ }}{ /* --------------- */

        showCount(elem, count)
        {
            let _= this;
            if(_.isNull(elem) || _.isNull(count)) {
                throw new GhrcNullException('elem', 'count'); 
            }

            elem.prepend("<span class='" + _.$.out.class + "' style='" + _.$.out.style 
                            + "'>" + count + "</span>");
        }

        process()
        {
            let _= this;
            _.dbg('started for: ' + location.pathname);

            let url = _.getInfoAPI();
            _.dbg('get info: ' + url);

            $.get(url, function(apidata)
            {
                $(_.$.pageFiles).each(function()
                {
                    let root = $(this);
                    let durl = root.attr('href');

                    if(durl.indexOf('releases/download') == -1) {
                        return true; // means 'continue' statement
                    }

                    for(let idx in apidata)
                    for(let asset in apidata[idx].assets)
                    {
                        let lnk = apidata[idx].assets[asset];

                        if(!lnk.browser_download_url.endsWith(durl)) {
                            continue;
                        };
                        
                        _.dbg('insert data for #' + lnk.id + ': ' + durl);
                        _.showCount(root, lnk.download_count);
                    }
                });
            });
        }

        constructor(debug)
        {
            super();

            this.$.debug = debug;
            this.process();
        }

        getInfoAPI()
        {
            let l = this.$.usrprj.exec(location.pathname);
            return location.protocol 
                    + '//' + this.$.apiserver + '/repos/' + l[1] + '/' + l[2] + '/releases';
        }

        dbg(msg, ...args)
        {
            if(!this.$.debug) {
                return;
            }

            let stamp = new Date().toISOString().substr(11, 12) + '] ';
            if(this.isNull(args) || args.length < 1) {
                console.log(stamp + msg);
            }
            else {
                console.log(stamp + msg, args);
            }
        }

        isNull(val)
        {
            return val == null || val === undefined;
        }
    };

    class GhrcException
    {
        constructor(message, arg)
        {
            this.message    = message;
            this.arg        = arg;
        }
    }

    class GhrcNullException extends GhrcException
    {
        constructor(...args)
        {
            super("'" + args + "' cannot be null.", null);
        }
    }


    // ...

    let ghrс = new GhrCounter(false);

    // when async loading
    $(window).bind('pjax:success', function() { ghrс.process(); });

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址