Github Stats

Display download stats about the last release of Github projects.

当前为 2016-11-07 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Github Stats
  3. // @namespace stratehm.github
  4. // @include https://github.com/*/*
  5. // @version 5
  6. // @grant GM_xmlhttpRequest
  7. // @grant GM_getValue
  8. // @grant GM_setValue
  9. // @grant GM_deleteValue
  10. // @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
  11. // @require https://greasyfork.org/scripts/2199-waitforkeyelements/code/waitForKeyElements.js
  12. // @description Display download stats about the last release of Github projects.
  13. // ==/UserScript==
  14.  
  15. var lastReleaseItemList;
  16. var cachedResponse;
  17.  
  18. this.$ = this.jQuery = jQuery.noConflict(true);
  19.  
  20. waitForKeyElements('.repohead-details-container', function () {
  21. init();
  22. });
  23.  
  24. function init() {
  25. lastReleaseItemList = $('<ul/>').attr({
  26. style: 'font-size: 11px; line-height: 10px; white-space: nowrap;'
  27. }).append('<b>Last release: </b>');
  28. $('div.repohead-details-container').find('h1').append(lastReleaseItemList);
  29. var userProject = getCurrentUserProjectUrlPart();
  30. if(userProject) {
  31. getDownloadCount(userProject);
  32. }
  33. if(window.location.pathname.indexOf("/settings/tokens") >= 0) {
  34. $('.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>&nbsp;&nbsp;<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>');
  35. $('#clientId').val(GM_getValue('clientId',''));
  36. $('#clientSecret').val(GM_getValue('clientSecret',''));
  37. $('#GM_submit').click(function() {
  38. GM_setValue("clientId",$('#clientId').val());
  39. GM_setValue("clientSecret",$('#clientSecret').val());
  40. console.log({clientId:GM_getValue("clientId"),clientSecret:GM_getValue("clientSecret")});
  41. $('#GM_submit').fadeTo(1000,0.01).fadeTo(1000,1);
  42. gotoSourceUrl();
  43. });
  44. $('#GM_done').fadeIn(1000).fadeOut(1000);
  45. $('#GM_reset').click(function(){
  46. $('#clientId').val('');
  47. $('#clientSecret').val('');
  48. GM_deleteValue("clientId");
  49. GM_deleteValue("clientSecret");
  50. $('#GM_reset').fadeTo(1000,0.01).fadeTo(1000,1);
  51. gotoSourceUrl();
  52. });
  53. } else {
  54. saveSourceUrl();
  55. }
  56. }
  57.  
  58. function getCurrentUserProjectUrlPart() {
  59. var splittedPath = window.location.pathname.split('/');
  60. if(splittedPath.length >= 3) {
  61. return splittedPath[1] + '/' + splittedPath[2];
  62. }
  63. }
  64.  
  65. function getDownloadCount(userProjectUserPart) {
  66. if(cachedResponse) {
  67. // Use the cached response if it exists.
  68. parseDownloadStatsResponse(cachedResponse);
  69. } else {
  70. var url = "https://api.github.com/repos/" + userProjectUserPart + "/releases";
  71. var headers = {
  72. "Cache-Control": "no-cache"
  73. }
  74. if(isTokenSet()) {
  75. headers.Authorization = "Basic " + btoa(GM_getValue("clientId")+":"+GM_getValue("clientSecret"));
  76. }
  77. GM_xmlhttpRequest({
  78. method: "GET",
  79. headers: headers,
  80. url: url,
  81. onload: onDownloadStatsResponse
  82. });
  83. }
  84. }
  85.  
  86. function onDownloadStatsResponse(response) {
  87. // Cache the response.
  88. cachedResponse = response;
  89. parseDownloadStatsResponse(response);
  90. }
  91.  
  92. function parseDownloadStatsResponse(response) {
  93. var status = response.status;
  94. var data = $.parseJSON(response.responseText);
  95. // Check if login credentials are accepted
  96. if(status == 401) {
  97. onUnauthorized();
  98. } else if(data.message && data.message.indexOf("API rate limit exceeded") >-1) {
  99. // Credentials are requested
  100. accessTokenNeeded();
  101. } else {
  102. // Parsing of the response only if some data are present.
  103. if(data && data.length > 0) {
  104. parseLastReleaseDownloadCount(data);
  105. parseTotalDownloadCount(data);
  106. } else {
  107. lastReleaseItemList.append("No release<br>");
  108. }
  109. if(isTokenSet()) {
  110. lastReleaseItemList.append("Change/Clear your <a href='https://github.com/settings/tokens'>Gihtub login credentials</a>");
  111. }
  112. }
  113. }
  114.  
  115. function parseLastReleaseDownloadCount(data) {
  116. var releaseName = data[0].name;
  117. var htmlUrl = data[0].html_url;
  118. lastReleaseItemList.append($('<a/>').attr({
  119. href: htmlUrl
  120. }).append(releaseName));
  121. if(data[0].assets && data[0].assets.length > 0) {
  122. for(var i = 0 ; i < data[0].assets.length ; i++) {
  123. var assetName = data[0].assets[i].name;
  124. var assetDlCount = data[0].assets[i].download_count;
  125. var assetUrl = data[0].assets[i].browser_download_url;
  126. appendAssetDlItem(assetName, assetDlCount, assetUrl);
  127. }
  128. } else {
  129. lastReleaseItemList.append("<br>No binaries in the last release<br>");
  130. }
  131. }
  132.  
  133. function parseTotalDownloadCount(data) {
  134. var totalDownloadCount = 0;
  135. for(var i = 0 ; i < data.length ; i++) {
  136. if(data[i].assets && data[i].assets.length > 0) {
  137. for(var j = 0 ; j < data[i].assets.length ; j++) {
  138. totalDownloadCount += data[i].assets[j].download_count;
  139. }
  140. }
  141. }
  142. lastReleaseItemList.append("All releases download count: " + totalDownloadCount + "<br>");
  143. }
  144.  
  145. function appendAssetDlItem(assetName, assetDlCount, assetUrl) {
  146. lastReleaseItemList.append($('<li/>').attr({
  147. style: "margin-left: 20px;"
  148. }).append("<b>Name:</b> <a href='" + assetUrl + "'>" + assetName + '</a>, <b>Dl Count:</b> ' + assetDlCount));
  149. }
  150.  
  151.  
  152. function accessTokenNeeded() {
  153. lastReleaseItemList.append($('<li/>').attr({
  154. style: "margin-left: 20px;"
  155. }).append("Your api limit has been hit. Please add a <a href='https://github.com/settings/tokens'>Gihtub login credentials</a>"));
  156. }
  157.  
  158. function onUnauthorized() {
  159. lastReleaseItemList.append($('<li/>').attr({
  160. style: "margin-left: 20px;"
  161. }).append("Bad credentials. Please check your <a href='https://github.com/settings/tokens'>Gihtub login credentials</a>"));
  162. }
  163.  
  164. function isTokenSet() {
  165. return GM_getValue("clientId","") && GM_getValue("clientSecret","");
  166. }
  167.  
  168. function saveSourceUrl() {
  169. GM_setValue("sourceUrl", window.location.href);
  170. }
  171. function gotoSourceUrl() {
  172. var sourceUrl = GM_getValue("sourceUrl", "");
  173. console.log("Restore location: " + sourceUrl);
  174. if(sourceUrl) {
  175. window.location.href = sourceUrl;
  176. }
  177. }