Advertisement
Guest User

Untitled

a guest
Aug 19th, 2022
364
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.30 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Catalog - Hotpocket Helper
  3. // @version 6.4
  4. // @author (cyg && fsn) == bffs 5 evr
  5. // @match https://boards.4chan.org/*/catalog
  6. // @match https://boards.4channel.org/*/catalog
  7. // @grant none
  8. // @run-at document-start
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict';
  13.  
  14. var CFCT = {};
  15.  
  16. CFCT.refresh = function() {
  17. CFCT.fetchReports();
  18. };
  19.  
  20. //Toolbox loaded, add the stuff
  21. CFCT.setupToolbox = function() {
  22. var toolbox = $.id("adminToolbox");
  23. var h4 = $.el("h4");
  24. toolbox.insertBefore(h4, toolbox.childNodes[2]);
  25.  
  26. var el = $.el("a");
  27. el.href = `http://reports.4chan.org/#/${CFCT.board}`;
  28. el.target = "_blank";
  29. el.setAttribute("data-tip", `Open /${CFCT.board}/ queue`);
  30. el.innerHTML = `/${CFCT.board}/ Reports`;
  31. h4.appendChild(el);
  32.  
  33. el = $.el("span");
  34. el.innerHTML = `: <span data-tip="Reports in queue" id="cfct-queue-count">?</span>`;
  35. el.innerHTML += ` (<a data-cmd="cfct-repfilter" data-tip="Threads with reported posts" id="cfct-thread-count">?</a>)`;
  36. h4.appendChild(el);
  37. };
  38.  
  39. //Use stats stored in CFCT to update toolbox
  40. CFCT.updateToolbox = function() {
  41. var scan = setInterval(function() {
  42. if ($.id("cfct-queue-count") && $.id("cfct-thread-count")) {
  43. clearInterval(scan);
  44. if (CFCT.reportCount) $.id("cfct-queue-count").innerHTML = CFCT.reportCount;
  45. else $.id("cfct-queue-count").innerHTML = 0;
  46. $.id("cfct-thread-count").innerHTML = CFCT.threadCount;
  47. }
  48. }, 50);
  49. };
  50.  
  51. CFCT.updateListeners = function() {
  52. $.on(document, "4chanATUpdated", CFCT.refresh);
  53. };
  54.  
  55. //Add HPH filter buttons to the catalog tools
  56. CFCT.setupFilters = function() {
  57. var spn = $.el("span");
  58. spn.innerHTML = "[<a href='javascript:void(0);' data-cmd='cfct-repfilter' id='cfct-repfilter' >Show Reported</a>] ";
  59. $.id("info").appendChild(spn);
  60.  
  61. spn = $.el("span");
  62. spn.innerHTML = "[<a href='javascript:void(0);' data-cmd='cfct-newfilter' id='cfct-newfilter' >Show New</a>]";
  63. $.id("info").appendChild(spn);
  64. };
  65.  
  66. //Add the report indicators based on stats generated in CFCT.buildStats
  67. CFCT.parsePage = function() {
  68. $.id("cfct-repfilter").style = "";
  69. $.id("cfct-newfilter").style = "";
  70.  
  71. var tmp = $.cls("cfct-parsed");//get all the previous parsed threads
  72. var prevParse = [];
  73. if (tmp[0]) {
  74. for (var i = 0; i < tmp.length; i++) {
  75. //push the post no of all the previous parsed threads into array
  76. //used to check if the thread still has reports or not
  77. prevParse.push(tmp[i].id.split("-")[1]);
  78. }
  79. }
  80.  
  81. for (var op in CFCT.threadCounts) {
  82. tmp = prevParse.indexOf(op);//if op exists in prevParse, remove it.
  83. if (tmp > -1) prevParse.splice(tmp, 1);//after we will only have post no's with no reports
  84.  
  85. if (!$.id(`meta-${op}`) || $.hasClass($.id(`thread-${op}`), "cfct-parsed")) {
  86. tmp = $.id("alert-id-" + op);
  87. if (tmp) {
  88. tmp.innerHTML = "[" + CFCT.threadCounts[op] + $.pluralise(CFCT.threadCounts[op], " Report", " Reports");
  89. if (CFCT.reportedOPs[op]) {
  90. tmp.innerHTML += " / OP Reported";
  91. }
  92. tmp.innerHTML += "]";
  93. }
  94. continue;
  95. }
  96.  
  97. $.addClass($.id(`thread-${op}`), "cfct-parsed")
  98.  
  99. var alert = $.el("div");
  100. alert.id = "alert-id-" + op;
  101. alert.className = "meta";
  102. alert.style.color = "red";
  103. alert.style.fontWeight = "700";
  104. alert.innerHTML = "[";
  105. alert.innerHTML += CFCT.threadCounts[op] + $.pluralise(CFCT.threadCounts[op], " Report", " Reports");
  106. if (CFCT.reportedOPs[op]) {
  107. alert.innerHTML += " / OP Reported";
  108. }
  109. alert.innerHTML += "]";
  110. $.id(`thread-${op}`).insertBefore(alert, $.id(`meta-${op}`).nextSibling);
  111. }
  112.  
  113. //loop through remaining post no's and remove the cfct-parsed
  114. //and remove the red alert indicator
  115. for (i = 0; i < prevParse.length; i++) {
  116. tmp = $.id("thread-" + prevParse[i]);
  117. if (tmp && $.hasClass(tmp, "cfct-parsed")) {
  118. $.removeClass(tmp, "cfct-parsed");
  119. tmp = $.id("alert-id-" + prevParse[i]);
  120. tmp.parentNode.removeChild(tmp);
  121. }
  122. }
  123. };
  124.  
  125. //Parse the report queue xhr response and generate thread report statistics
  126. CFCT.buildStats = function() {
  127. var report, reports = CFCT.xhr.data.reports;
  128. var threadCounts = {};
  129. var reportedOPs = {};
  130. CFCT.threadCount = 0;
  131. CFCT.reportCount = CFCT.xhr.data.counts[CFCT.board];
  132.  
  133. for (var i = 0; (report = reports[i]); ++i) {
  134. try {
  135. var post = JSON.parse(report.post);
  136. } catch(e) {
  137. console.log(`error parsing post ${report.no}`);
  138. console.log(e);
  139. }
  140.  
  141. var parent = (post.resto == 0) ? post.no : post.resto;
  142. if (post.resto == 0) {
  143. reportedOPs[post.no] = 1;
  144. }
  145. if (!threadCounts[parent]) {
  146. threadCounts[parent] = 1;
  147. CFCT.threadCount++;
  148. } else {
  149. threadCounts[parent]++;
  150. }
  151. }
  152.  
  153. CFCT.threadCounts = threadCounts;
  154. CFCT.reportedOPs = reportedOPs;
  155.  
  156. var scan = setInterval(function() {
  157. if ($.cls("thread").length > 0) {
  158. clearInterval(scan);
  159. $.dispatch("CFTCReportsParsed");
  160. CFCT.updateToolbox();
  161. CFCT.monitor = new MutationObserver(CFCT.parsePage);
  162. CFCT.monitor.observe($.id("threads"), {childList:true});
  163. }
  164. }, 50);
  165. };
  166.  
  167. //XHR request retrieves list of reports.
  168. CFCT.fetchReports = function() {
  169. $.xhr("GET", `https://reports.4chan.org/?action=get_reports&board=${CFCT.board}`, {
  170. onreadystatechange: function() {
  171. if (this.status == 200 && this.readyState == 4) {
  172. try {
  173. var dat = JSON.parse(this.responseText);
  174. } catch (e) {
  175. console.log("error parsing reports");
  176. console.log(e);
  177. }
  178. if (dat.status != "success") {
  179. console.log("error parsing reports or you don't have this board.");
  180. return;
  181. }
  182. CFCT.xhr = dat;
  183. CFCT.buildStats(); //Sort out everything....
  184. }
  185. },
  186. onerror: function() {
  187. console.log("error fetching reports or you don't have this board.");
  188. }
  189. }, null, true);
  190. };
  191.  
  192. //Toggle filter threads with reports
  193. CFCT.filterReported = function() {
  194. var bfw, op, ops = $.cls("thread"), button = $.id("cfct-repfilter");
  195. //hold on to yuor butts
  196. button.style.fontWeight = (button.style.fontWeight == 700) ? 500 : 700;
  197. bfw = button.style.fontWeight;
  198.  
  199. for (var i = 0; (op = ops[i]); ++i) {
  200. if (bfw == 700) { //filter turn on
  201. button.style.color = "red";
  202. if (!$.hasClass(op, "cfct-parsed")) {
  203. op.style.display = "none";
  204. }
  205. } else { //filter turn off
  206. op.style.display = "";
  207. button.style.color = "";
  208. }
  209. }
  210. };
  211.  
  212. //Toggle displaying threads made since timestamp CFCT.prevTime
  213. CFCT.filterNew = function() {
  214. if (!CFCT.prevTime) return;
  215. var bfw, button = $.id("cfct-newfilter");
  216. //hold on to yuor butts pt 2
  217. button.style.fontWeight = (button.style.fontWeight == 700) ? 500 : 700;
  218. bfw = button.style.fontWeight;
  219.  
  220. if (bfw == 700) {
  221. button.style.color = "red";
  222. for (var no in window.catalog.threads) {
  223. var thread = window.catalog.threads[no];
  224. if (thread.date < CFCT.prevTime) {
  225. if ($.id(`thread-${no}`)) {
  226. $.id(`thread-${no}`).style.display = "none";
  227. }
  228. }
  229. }
  230. } else {
  231. button.style.color = "";
  232. var op, ops = $.cls("thread");
  233. for (var i = 0; (op = ops[i]); ++i) {
  234. op.style.display = "";
  235. }
  236. }
  237. };
  238.  
  239. CFCT.onClick = function(e) {
  240. var t = e.target;
  241. switch(t.getAttribute("data-cmd")) {
  242. case "cfct-repfilter":
  243. CFCT.filterReported();
  244. break;
  245. case "cfct-newfilter":
  246. CFCT.filterNew();
  247. break;
  248. default: break;
  249. }
  250. };
  251.  
  252. CFCT.getStyle = function() { //this looks familiar hmmmm :thinking:
  253. var i, a, link, sheet;
  254.  
  255. for (i = 0;
  256. (a = document.getElementsByTagName("link")[i]); i++) {
  257. if (a.getAttribute("title") == "switch") {
  258. link = a;
  259. } else if (a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && a.href == link.href) {
  260. sheet = a.getAttribute("title");
  261. }
  262. }
  263.  
  264. switch(sheet) {
  265. case "Tomorrow": sheet = "tomorrow"; break;
  266. case "Photon": sheet = "photon"; break;
  267. case "Yotsuba B New": //pass through
  268. case "Burichan New": sheet = "burichan"; break;
  269. case "Yotsuba New": //pass through
  270. case "Futaba New": sheet = "futaba"; break;
  271. default: sheet = (window.style_group == "ws_style") ? "burichan" : "futaba"; break;
  272. }
  273. CFCT.style = sheet;
  274. };
  275.  
  276. if($)$.remByID=function(e){var n=$.id(e);n&&n.parentNode.removeChild(n)};else{var $={id:function(e){return document.getElementById(e)},remByID:function(e){var n=$.id(e);n&&n.parentNode.removeChild(n)},cls:function(e,n){return(n||document).getElementsByClassName(e)},byName:function(e){return document.getElementsByName(e)},tag:function(e,n){return(n||document).getElementsByTagName(e)},el:function(e){return document.createElement(e)},el2:function(e,n,t,i){var o,r;o=$.el(e);for(r in t)o.setAttribute(r,t[r]);return i&&(o.innerHTML=i),n.appendChild(o)},frag:function(){return document.createDocumentFragment()},qs:function(e,n){return(n||document).querySelector(e)},qsa:function(e,n){return(n||document).querySelectorAll(e)},extend:function(e,n){for(var t in n)e[t]=n[t]}};document.documentElement.classList?($.hasClass=function(e,n){return e.classList.contains(n)},$.addClass=function(e,n){e.classList.add(n)},$.removeClass=function(e,n){e.classList.remove(n)}):($.hasClass=function(e,n){return-1!=(" "+e.className+" ").indexOf(" "+n+" ")},$.addClass=function(e,n){e.className=""===e.className?n:e.className+" "+n},$.removeClass=function(e,n){e.className=(" "+e.className+" ").replace(" "+n+" ","")}),$.on=function(e,n,t){e.addEventListener(n,t,!1)},$.dispatch=function(e,n){var t=document.createEvent("Event");t.initEvent(e,!1,!1),document.dispatchEvent(t)},$.off=function(e,n,t){e.removeEventListener(n,t,!1)},$.xhr=function(e,n,t,i,o,r){var s,c,a;if(o=!!o||0,(c=new XMLHttpRequest).open(e,n,!0),t)for(s in t)c[s]=t[s];if(i)if("string"==typeof i)c.setRequestHeader("Content-type","application/x-www-form-urlencoded");else{a=new FormData;for(s in i)a.append(s,i[s]);console.log(r),console.log(a),i=a}else i=null;return o&&(c.withCredentials=!0),c.send(i),c},$.getItem=function(e){return localStorage.getItem(e)},$.setItem=function(e,n){return localStorage.setItem(e,n)},$.removeItem=function(e){return localStorage.removeItem(e)},$.getCookie=function(e){var n,t,i,o;for(o=e+"=",i=document.cookie.split(";"),n=0;t=i[n];++n){for(;" "==t.charAt(0);)t=t.substring(1,t.length);if(0===t.indexOf(o))return decodeURIComponent(t.substring(o.length,t.length))}return null},$.toggleXls=function(e,n){$.hasClass(e,n)?$.removeClass(e,n):$.addClass(e,n)},$.getToken=function(){return document.body.getAttribute("data-tkn")},$.capitalise=function(e){return e.charAt(0).toUpperCase()+e.slice(1)},$.pluralise=function(e,n,t){return 1===e?n||"":t||"s"},$.prettyBytes=function(e){return e>=1048576?(0|e/1048576*100+.5)/100+" MB":e>1024?(0|e/1024+.5)+" KB":e+" B"},$.ago=function(e){var n,t,i,o;return(n=Date.now()/1e3-e)<1?"recent":60>n?(0|n)+" secs":3600>n?(t=0|n/60)>1?t+" mins":"1 min":86400>n?(i=(t=0|n/3600)>1?t+"":"1",i+="."+(o=0|n/60-60*t)+" hrs"):(i=(t=0|n/86400)>1?t+"":"1",(o=0|n/3600-24*t)>=1&&(i+="."+o+" days"),i+"")},$.now=function(){return Math.round((new Date).getTime()/1e3)},$.length=function(e){return Object.keys(e).length},$.hidden="hidden",$.visibilitychange="visibilitychange",void 0===document.hidden&&("mozHidden"in document?($.hidden="mozHidden",$.visibilitychange="mozvisibilitychange"):"webkitHidden"in document?($.hidden="webkitHidden",$.visibilitychange="webkitvisibilitychange"):"msHidden"in document&&($.hidden="msHidden",$.visibilitychange="msvisibilitychange")),$.docEl=document.documentElement}
  277.  
  278. CFCT.board = window.location.href.split("/")[3];
  279. CFCT.domain = (/4channel/.test(window.location.href)) ? "4channel" : "4chan";
  280. CFCT.prevTime = $.getItem(`cfct-refresh-time-${CFCT.board}`);
  281. $.setItem(`cfct-refresh-time-${CFCT.board}`, $.now());
  282.  
  283. CFCT.fetchReports();
  284. CFCT.getStyle(); //twice on purpose
  285.  
  286. //$.on(document, "DOMContentLoaded", CFCT.setupFilters);
  287. $.on(document, "CFTCReportsParsed", CFCT.parsePage);
  288. setTimeout(CFCT.updateListeners, 5000);
  289. $.on(document, "click", CFCT.onClick);
  290.  
  291. var filterscan = setInterval(function() {
  292. if ($.id("info")) {
  293. clearInterval(filterscan);
  294. CFCT.setupFilters();
  295. }
  296. }, 50);
  297.  
  298. var toolscan = setInterval(function() {
  299. if ($.id("adminToolbox")) {
  300. clearInterval(toolscan);
  301. CFCT.setupToolbox();
  302. }
  303. }, 50);
  304. })();
  305.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement