NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Github Stats // @namespace stratehm.github // @include https://github.com/*/* // @version 7 // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js // @require https://greasyfork.org/scripts/2199-waitforkeyelements/code/waitForKeyElements.js // ==/UserScript== var lastReleaseItemList; var cachedResponse; this.$ = this.jQuery = jQuery.noConflict(true); waitForKeyElements('.repohead-details-container', function () { init(); }); function init() { $('#ulLastReleaseItems').remove(); lastReleaseItemList = $('<ul id="ulLastReleaseItems"/>').attr({ style: 'font-size: 11px; line-height: 10px; white-space: nowrap;' }).append('<b>Last release: </b>'); $('div.repohead-details-container').find('h1').append(lastReleaseItemList); var userProject = getCurrentUserProjectUrlPart(); if(userProject) { getDownloadCount(userProject); } if(window.location.pathname.indexOf("/settings/tokens") >= 0) { $('.column.three-fourths').append('<div class="boxed-group access-token-group" id="GM_Form"><h3>Set your Gihtub login credentials for the GreaseMonkey userscript</h3><div class="boxed-group-inner"><p>Your login credentials will be used by the userscript to show the number of downloads for repositories.</p><ul class="boxed-group-list"><li style="line-height:32px;"><p>Username: <input type="text" id="clientId" style="float:right;width:480px;" /></p><p style="line-height:32px;">Password: <input type="password" id="clientSecret" style="float:right;width:480px;"/></p></li><li><button id="GM_submit" type="submit" type="button" class="btn btn-primary">Save</button> <button id="GM_reset" type="submit" type="button" class="btn btn-danger">Clear</button></li></ul><p class="help"><i class="octicon octicon-question"></i>Without your login credentials, you are rate limited to <a href="https://developer.github.com/v3/#rate-limiting">60 api calls per hour</a>.</p></div></div>'); $('#clientId').val(GM_getValue('clientId','')); $('#clientSecret').val(GM_getValue('clientSecret','')); $('#GM_submit').click(function() { GM_setValue("clientId",$('#clientId').val()); GM_setValue("clientSecret",$('#clientSecret').val()); console.log({clientId:GM_getValue("clientId"),clientSecret:GM_getValue("clientSecret")}); $('#GM_submit').fadeTo(1000,0.01).fadeTo(1000,1); gotoSourceUrl(); }); $('#GM_done').fadeIn(1000).fadeOut(1000); $('#GM_reset').click(function(){ $('#clientId').val(''); $('#clientSecret').val(''); GM_deleteValue("clientId"); GM_deleteValue("clientSecret"); $('#GM_reset').fadeTo(1000,0.01).fadeTo(1000,1); gotoSourceUrl(); }); } else { saveSourceUrl(); } } function getCurrentUserProjectUrlPart() { var splittedPath = window.location.pathname.split('/'); if(splittedPath.length >= 3) { return splittedPath[1] + '/' + splittedPath[2]; } } function getDownloadCount(userProjectUserPart) { if(cachedResponse) { // Use the cached response if it exists. parseDownloadStatsResponse(cachedResponse); } else { var url = "https://api.github.com/repos/" + userProjectUserPart + "/releases"; var headers = { "Cache-Control": "no-cache" } if(isTokenSet()) { headers.Authorization = "Basic " + btoa(GM_getValue("clientId")+":"+GM_getValue("clientSecret")); } GM_xmlhttpRequest({ method: "GET", headers: headers, url: url, onload: onDownloadStatsResponse }); } } function onDownloadStatsResponse(response) { // Cache the response. cachedResponse = response; parseDownloadStatsResponse(response); } function parseDownloadStatsResponse(response) { var status = response.status; var data = $.parseJSON(response.responseText); // Check if login credentials are accepted if(status == 401) { onUnauthorized(); } else if(data.message && data.message.indexOf("API rate limit exceeded") >-1) { // Credentials are requested accessTokenNeeded(); } else { // Parsing of the response only if some data are present. if(data && data.length > 0) { parseLastReleaseDownloadCount(data); parseTotalDownloadCount(data); } else { lastReleaseItemList.append("No release<br>"); } if(isTokenSet()) { lastReleaseItemList.append("Change/Clear your <a href='https://github.com/settings/tokens'>Gihtub login credentials</a>"); } } } function parseLastReleaseDownloadCount(data) { var releaseName = data[0].name; var releaseDate = data[0].published_at; var htmlUrl = data[0].html_url; lastReleaseItemList.append($('<a/>').attr({ href: htmlUrl, title: formatDate(releaseDate) }).append(releaseName)); if(data[0].assets && data[0].assets.length > 0) { for(var i = 0 ; i < data[0].assets.length ; i++) { var assetName = data[0].assets[i].name; var assetDlCount = data[0].assets[i].download_count; var assetUrl = data[0].assets[i].browser_download_url; appendAssetDlItem(assetName, assetDlCount, assetUrl); } } else { lastReleaseItemList.append("<br>No binaries in the last release<br>"); } } function parseTotalDownloadCount(data) { var totalDownloadCount = 0; for(var i = 0 ; i < data.length ; i++) { if(data[i].assets && data[i].assets.length > 0) { for(var j = 0 ; j < data[i].assets.length ; j++) { totalDownloadCount += data[i].assets[j].download_count; } } } lastReleaseItemList.append("All releases download count: " + totalDownloadCount + "<br>"); } function appendAssetDlItem(assetName, assetDlCount, assetUrl) { lastReleaseItemList.append($('<li/>').attr({ style: "margin-left: 20px;" }).append("<b>Name:</b> <a href='" + assetUrl + "'>" + assetName + '</a>, <b>Dl Count:</b> ' + assetDlCount)); } function accessTokenNeeded() { lastReleaseItemList.append($('<li/>').attr({ style: "margin-left: 20px;" }).append("Your api limit has been hit. Please add a <a href='https://github.com/settings/tokens'>Gihtub login credentials</a>")); } function onUnauthorized() { lastReleaseItemList.append($('<li/>').attr({ style: "margin-left: 20px;" }).append("Bad credentials. Please check your <a href='https://github.com/settings/tokens'>Gihtub login credentials</a>")); } function isTokenSet() { return GM_getValue("clientId","") && GM_getValue("clientSecret",""); } function saveSourceUrl() { GM_setValue("sourceUrl", window.location.href); } function gotoSourceUrl() { var sourceUrl = GM_getValue("sourceUrl", ""); console.log("Restore location: " + sourceUrl); if(sourceUrl) { window.location.href = sourceUrl; } } function formatDate(dateToFormat) { var dateSeconds = Date.parse(dateToFormat); // build a date object with the (timezone-agnostic) timepoint var date = new Date(dateSeconds); // format the date according to locale's rules return date.toLocaleString(); }