[GMT] Highlight changes in upload snatches

Highlight changes in own upload snatches

  1. // ==UserScript==
  2. // @name [GMT] Highlight changes in upload snatches
  3. // @namespace https://greasyfork.org/users/321857-anakunda
  4. // @version 1.00.0
  5. // @match https://*/torrents.php?*
  6. // @run-at document-end
  7. // @author Anakunda
  8. // @copyright 2021, Anakunda (https://greasyfork.org/users/321857-anakunda)
  9. // @license GPL-3.0-or-later
  10. // @description Highlight changes in own upload snatches
  11. // @grant GM_getValue
  12. // @grant GM_setValue
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. const params = new URLSearchParams(document.location.search);
  19. let snapshot, touched = false, counter = 0;
  20.  
  21. function getTorrentId(node) {
  22. if (node instanceof HTMLElement) for (let a of node.getElementsByTagName('A')) {
  23. if (a.pathname != '/torrents.php') continue;
  24. let torrentId = new URLSearchParams(a.search).get('torrentid');
  25. if (torrentId) return parseInt(torrentId);
  26. }
  27. }
  28.  
  29. function foo(torrentId, snatchesColumn) {
  30. if (!torrentId || !(snatchesColumn instanceof HTMLElement)) return; // assertion failed
  31. const snatches = parseInt(snatchesColumn.textContent);
  32. if (!(snatches >= 0) || snatches == snapshot[torrentId]) return;
  33. if (snapshot[torrentId] >= 0) {
  34. ++counter;
  35. let span = document.createElement('span');
  36. span.textContent = snatches > snapshot[torrentId] ?
  37. '+' + (snatches - snapshot[torrentId]) : snatches - snapshot[torrentId];
  38. span.style = `
  39. margin-left: 4px; border: solid 1px black;
  40. padding: 0 3px; font-weight: 600;
  41. background-color: yellow; color: black;
  42. `;
  43. span.className = 'delta';
  44. snatchesColumn.append(span);
  45. }
  46. snapshot[torrentId] = snatches; touched = true;
  47. }
  48.  
  49. switch (document.location.pathname.slice(1)) {
  50. case 'torrents.php':
  51. if (params.get('type') == 'uploaded') {
  52. var selector = 'table.torrent_table > tbody > tr.torrent';
  53. snapshot = GM_getValue(document.domain, { });
  54. for (let tr of document.body.querySelectorAll(selector)) {
  55. const torrentId = getTorrentId(tr);
  56. if (torrentId > 0) foo(torrentId, tr.children[4]);
  57. const leechers = parseInt(tr.children[6].textContent);
  58. if (leechers > 0) tr.children[6].style = 'color: green; font-weight: bold;';
  59. }
  60. } else if (params.get('id') > 0) {
  61. selector = 'table#torrent_details > tbody > tr.torrent_row';
  62. snapshot = GM_getValue(document.domain, { });
  63. for (let tr of document.body.querySelectorAll(selector)) {
  64. if (tr.querySelector('span.torrent_action_buttons > a.button_rm') == null) continue; // not own upload
  65. let torrentId = /^(?:torrent(\d+))$/i.exec(tr.id);
  66. if (torrentId != null) foo(parseInt(torrentId[1]), tr.children[2]);
  67. const leechers = parseInt(tr.children[4].textContent);
  68. if (leechers > 0) tr.children[4].style = 'color: green; font-weight: bold;';
  69. }
  70. }
  71. break;
  72. }
  73. if (touched > 0) GM_setValue(document.domain, snapshot);
  74. if (counter > 0) {
  75. let div = document.createElement('DIV');
  76. div.innerHTML = '<span class="deltacounter">' + counter + '</span> ' +
  77. (counter != 1 ? 'changes' : 'change') + ' in snatches';
  78. div.style = `
  79. position: fixed; right: 20px; top: 20px;
  80. opacity: 1; transition: opacity 1s ease-in-out;
  81. border: solid 3px darkorange;
  82. padding: 5px;
  83. color: darkorange; background: antiquewhite;
  84. font: 12pt bold;
  85. box-shadow: 0 0 10px orange;
  86. cursor: pointer;
  87. z-index: 999999;
  88. `;
  89. if (selector) div.onclick = function(evt) {
  90. for (let elem of document.body.querySelectorAll(selector))
  91. if (elem.querySelector('span.delta') == null) elem.style.visibility = 'collapse';
  92. if (evt.currentTarget.hTimer) clearTimeout(evt.currentTarget.hTimer);
  93. evt.currentTarget.remove();
  94. };
  95. document.body.append(div);
  96. const delay = GM_getValue('toast_timeout', 10);
  97. if (delay > 0) {
  98. //setTimeout(div => { div.style.opacity = 1 }, 0, div);
  99. div.hTimer = setTimeout(div => {
  100. div.style.opacity = 0;
  101. div.hTimer = setTimeout(div => { div.remove() }, 1000, div);
  102. }, (delay + 1) * 1000, div);
  103. }
  104. }
  105. })();