mozillaZine Forums - insert titles to bug links

Inserts titles to bug links that are plain URLs, in forums.mozillazine.org

  1. // ==UserScript==
  2. // @name mozillaZine Forums - insert titles to bug links
  3. // @namespace darkred
  4. // @version 2017.11.16
  5. // @description Inserts titles to bug links that are plain URLs, in forums.mozillazine.org
  6. // @author darkred, johnp_
  7. // @license MIT
  8. // @include http://forums.mozillazine.org/viewtopic.php*
  9. // @grant none
  10. // @require https://code.jquery.com/jquery-2.1.4.min.js
  11. // @supportURL https://github.com/darkred/Userscripts/issues
  12. // ==/UserScript==
  13.  
  14. // v2.0: Script rewrite (based on johnp_'s contribution in the userscript 'Firefox for desktop - list fixed bugs in Mercurial'):
  15. // now the REST API is used (one(1) network connection is made for all unique examined bug IDs)
  16.  
  17.  
  18. /* eslint-disable no-console */
  19.  
  20.  
  21.  
  22. var silent = false;
  23. var debug = false;
  24.  
  25. time('MozillaBugzilla');
  26.  
  27.  
  28. var regex = /^https:\/\/bugzilla\.mozilla\.org\/show_bug\.cgi\?id=([0-9]*).*$/;
  29. var base_url = 'https://bugzilla.mozilla.org/rest/bug?include_fields=id,summary,status&id=';
  30. var bugIds = [];
  31. var bugCodes = [];
  32. var bugTitles = [];
  33. var links = document.getElementsByClassName('postlink');
  34. var len = links.length;
  35.  
  36.  
  37. for (let i = 0; i < len; i++) {
  38. let n = links[i].href.match(regex);
  39. let n2 = links[i].innerHTML;
  40. if (n !== null &&
  41. n2.match(/^#[0-9]*/) === null &&
  42. n2.indexOf('-') === -1) {
  43. let id = parseInt(n[1]);
  44. if (bugIds.indexOf(id) === -1) {
  45. bugIds.push(id);
  46. }
  47. }
  48. }
  49.  
  50.  
  51.  
  52. var numBugs = bugIds.length;
  53. var counter = 0;
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61. var rest_url = base_url + bugIds.join();
  62. time('MozillaBugzilla-REST');
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73. // ADDING a spinning icon to the matching links
  74. for (var i = 0; i < links.length; i++) {
  75. if ( links[i].href.match(regex)
  76. && links[i].innerHTML.match(/#[0-9]*/) == null
  77. && links[i].innerHTML.indexOf('-') == -1 ) {
  78. var elem = document.createElement('img');
  79. // var elem;
  80. //(async function() {
  81. // elem = document.createElement('img');
  82. // elem.src = GM.getResourceUrl('icon');
  83.  
  84.  
  85. var rotatingIcon_base64 = `data:image/gif;base64,R0lGODlhEAAQAPIAAP///8LCwkJCQgAAAGJiYoKCgpKSkgAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrC0IEKsYQnAdOmGYFBLExwboQWcG2LlDEgWHQLUsUOd2mBzEUCgZKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P4uCBEgE2MIu7DmikRxAUFUIDEVIFBMRFsWqGwYtXXfrVEUBkAg1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIuiESK0oxhpCskFYvBoRTGA70FQ7xSQFRmGtgGPAKzLO9GMWoKwFZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIulEUK0oiRJHMmFZfhYumBUQRCMMgREZRGBGqRkGw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIumEWK0rnZAzQlPIKgQwmdoJQXGJElISEuR5oWUEpz4owDAIe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6EMGQORfjdMa82l4oGccYoCEuQbadykesYiEIBQsQM2G7sDX3FcFgILAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7whRDZnFVdmgHummFwVVCInVGc3TSWREFGhCAQUGCbdgEJg4EgEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlIdScKdceCASCII6GcQrDIDCpyrBuQBSBURQGVtolAiB1YhSCnlsRkAAAOw==`;
  86. elem.src = rotatingIcon_base64;
  87.  
  88.  
  89.  
  90. links[i].parentNode.insertBefore(elem, links[i].nextSibling); // For spinning icon AFTER the link
  91.  
  92. // })();
  93. // links[i].parentNode.insertBefore(elem, links[i].previousSibling); // For spinning icon BEFORE the link
  94. }
  95. }
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109. $.getJSON(rest_url, function(data) {
  110. timeEnd('MozillaBugzilla-REST');
  111.  
  112.  
  113. $.each(data.bugs, function(index) {
  114. let bug = data.bugs[index];
  115. let status = bug.status;
  116.  
  117. log('----------------------------------------------------------------------------------------------------------------------------------');
  118. log((index + 1) + '/' + numBugs); // Progression counter
  119.  
  120. log('BugNo: ' + bug.id + '\nTitle: ' + bug.summary);
  121.  
  122.  
  123.  
  124. bugCodes.push(bug.id);
  125. bugTitles.push(bug.summary);
  126.  
  127.  
  128. counter++; // increase counter
  129.  
  130. let i = bugIds.indexOf(bug.id);
  131. if (i !== -1) {bugIds[i] = null;}
  132. });
  133. log('==============\nReceived ' + counter + ' of ' + numBugs + ' bugs.');
  134.  
  135. // process remaining bugs one-by-one
  136. var requests = [];
  137. time('MozillaBugzilla-missing');
  138. $.each(bugIds, function(index) {
  139. let id = bugIds[index];
  140. if (id !== null) {
  141. time('Requesting missing bug ' + id);
  142. let promise = $.getJSON('https://bugzilla.mozilla.org/rest/bug/' + id,
  143. function(json) {
  144. // I've not end up here yet, so cry if we do
  145. console.error('Request succeeded unexpectedly!');
  146. console.error('Please submit this information to the script authors:');
  147. timeEnd('Requesting missing bug ' + id);
  148. console.log(json);
  149. let bug = json.bugs[0];
  150. console.log(bug);
  151. // TODO: display as much information as possible
  152. });
  153. // Actually, we usually get an error
  154. promise.error(function(req, status, error) {
  155. timeEnd('Requesting missing bug ' + id);
  156. if (error == 'Authorization Required') {
  157. log('Bug ' + id + ' requires authorization!');
  158. // log('https://bugzilla.mozilla.org/show_bug.cgi?id=' + id + ' requires authorization!');
  159. } else {
  160. console.error('Unexpected error encountered (Bug' + id + '): ' + status + ' ' + error);
  161. }
  162. });
  163. requests.push(promise);
  164. }
  165. });
  166. // wait for all requests to be settled, then join them together
  167. // Source: https://stackoverflow.com/questions/19177087/deferred-how-to-detect-when-every-promise-has-been-executed
  168. $.when.apply($, $.map(requests, function(p) {
  169. return p.then(null, function() {
  170. return $.Deferred().resolveWith(this, arguments);
  171. });
  172. })).always(function() {
  173. timeEnd('MozillaBugzilla-missing');
  174.  
  175. // console.log(bugCodes);
  176.  
  177. for (let z=0; z < links.length; z++) {
  178.  
  179. loop2:
  180. for (let yy=0; yy < bugCodes.length; yy++) {
  181.  
  182. if (regex.test(links[z].href)
  183. && links[z].href.match(regex)[1] == bugCodes[yy]
  184. && links[z].innerHTML.indexOf('-') == -1 ) {
  185.  
  186. let temp = links[z].innerHTML.match(/([Bb]ug\ [a-zA-Z]*).*[0-9]*/i);
  187. var temp2 = links[z].href.match(/^https:\/\/bugzilla\.mozilla\.org\/show_bug\.cgi\?id=[0-9]*(.*)$/);
  188. // if (temp !== null) {
  189. // links[z].previousSibling.textContent += temp[1] + ' ';
  190. // links[z].innerHTML = bugCodes[yy] + ' - ' + bugTitles[yy] + temp2[1];
  191. // } else {
  192. // links[z].innerHTML = bugCodes[yy] + ' - ' + bugTitles[yy] + temp2[1];
  193. // }
  194. if (temp !== null) {
  195. links[z].previousSibling.textContent += temp[1] + ' ';
  196. }
  197. links[z].innerHTML = bugCodes[yy] + ' - ' + bugTitles[yy] + temp2[1];
  198.  
  199. break loop2;
  200. }
  201.  
  202. }
  203.  
  204.  
  205. if (links[z].nextSibling && links[z].nextSibling.src === rotatingIcon_base64){
  206. links[z].nextSibling.remove(); // For REMOVE spinning icon AFTER the link
  207. // x.previousSibling.previousSibling.remove(); // For REMOVE spinning icon BEFORE the link
  208. if (links[z].innerHTML.indexOf('https://bugzilla.mozilla.org') !== -1 ){
  209. links[z].innerHTML += ' &nbsp<i>(requires authorization)</i>';
  210. }
  211. }
  212.  
  213. }
  214. log('ALL IS DONE');
  215. timeEnd('MozillaBugzilla');
  216. });
  217. });
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225. function log(str) {
  226. if (!silent) {
  227. console.log(str);
  228. }
  229. }
  230.  
  231. function time(str) {
  232. if (debug) {
  233. console.time(str);
  234. }
  235. }
  236.  
  237. function timeEnd(str) {
  238. if (debug) {
  239. console.timeEnd(str);
  240. }
  241. }