Advertisement
Guest User

Untitled

a guest
Mar 6th, 2019
238
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.28 KB | None | 0 0
  1. // ==UserScript==
  2. // @description Автообоссывание кремлеботов и пидорватных дегенератов.
  3. // @exclude https://2ch.hk/po/catalog.html
  4. // @exclude https://2ch.hk/news/catalog.html
  5. // @include https://2ch.hk/po/*
  6. // @include https://2ch.hk/news/*
  7. // @icon https://2ch.hk/favicon.ico
  8. // @name 2ch autoHide
  9. // @name:ru 2ch автообоссывание по списку спеллов own
  10. // @namespace poRussia
  11. // @run-at document-end
  12. // @version 190305
  13. // ==/UserScript==
  14.  
  15.  
  16. // ВНИМАНИЕ! СКРИПТ НЕСОВМЕСТИМ С ДРУГИМИ ВАРИАНТАМИ АВТОСКРЫТИЯ! - пиздеж
  17. // (такими как через куклоскрипт или через настройки 2ch)
  18.  
  19. const POST = 1;
  20. const BOTH = 2;
  21. const HEAD = 3;
  22. const RAGE = 1;
  23. const HIDE = 3;
  24.  
  25. // ============[НАЧАЛО НАСТРОЕК]============
  26. // клики по дизлайкам ставятся в случайном интервале между этими двумя значениями
  27. const minClickDelay = 5500; // минимальная задержка между кликами, мс
  28. const maxClickDelay = 7000; // максимальная задержка между кликами, мс
  29.  
  30. const showInTitle = 0; // Показывать счётчик дизлайков в заголовке вкладки браузера? 1 = да, 0 = нет
  31. const ignoreQuotes = 1; // Игнорировать совпадения выражений в >цитируемом тексте? 1 = да, 0 = нет
  32. /* ignoreQuotes = 0 проверяет чистый текст, поэтому будет работать быстрее и проще, но не позволит
  33. игнорировать совпадения регулярных выражений в цитируемом тексте и будет скрывать посты, в которых
  34. наивный анон цитирует животных и ботов, чтобы им ответить.
  35. ignoreQuotes = 1 проверяет текст с тегами, поэтому не будет ставить RAGE и скрывать посты из-за цитат,
  36. также конструкции типа св[b][/b]инья будут корректно определены, но этот метод работает чуть медленнее
  37. (разница составляет миллисекунды, но на некрокомпах может быть заметно).
  38. Рекомендуется использовать ignoreQuotes = 1.
  39. */
  40. const popupChars = 500; // Количество символов во всплывающей подсказке над скрытым постом.
  41. // Наведи на слово 'hide', чтобы увидеть подсказку.
  42.  
  43. const highlight = 1; // Подсвечивать посты зелёным/красным? 1 = да, 0 = нет
  44.  
  45. /*Вложенный массив с регулярными выражениями для скрытия/лайков.
  46. Первый элемент - место поиска выражения:
  47. POST - искать только в тексте поста;
  48. BOTH - искать и в тексте, и в заголовке;
  49. HEAD - искать только в заголовке треда(для скрытия номерных тредов например).
  50. Второй элемент - действие при обнаружении:
  51. RAGE - ставить дизлайк;
  52. BOTH - ставить дизлайк и скрывать;
  53. HIDE - просто скрытие.
  54. Третий элемент - регулярное выражение.
  55. Четвёртый элемент - краткое описание, которое появится в заголовке скрытого поста/треда.
  56.  
  57. Узнать больше про регулярные выражения можно тут:
  58. https://www.google.com/search?q=regex+javascript
  59. Потестировать работоспособность и создать спеллы можно тут:
  60. https://regex101.com/
  61. (не забыть слева выбрать "ECMAScript (JavaScript)", справа от строки во флагах выбрать /imu)
  62.  
  63. [где искать, что делать, /регулярное выражение/imu, "описание"]*/
  64. const regexArray = [
  65. [BOTH, RAGE, /(^|\s)[aaoo]?л[еeё]ш([еe]нь)?к[аaуyиеe]/imu, "алёшка"],
  66. [BOTH, RAGE, /(^|\s)[сc]?к[аaоo]к[хx]?[еeёоo]?л/imu, "какол"],
  67. [BOTH, RAGE, /к(ибер|опро)сот/imu, "киберсотня"],
  68. [BOTH, RAGE, /[кk][рp]я[кk]л/imu, "крякл"],
  69. [BOTH, RAGE, /л[еe][хx][аa]и[мm]/imu, "лехаим"],
  70. [BOTH, RAGE, /л[еeиuя][б6][еeиuуy][рp]([дg]|[аa][кkнhсcхxш]|[оo][иu][дg])/imu, "либераш"],
  71. [BOTH, RAGE, /[мm][аa]й[дg][аa][уy]н/imu, "майдаун"],
  72. [BOTH, RAGE, /(^|\s)[мm][аa][нh]я([.,\s]|$)/imu, "маня"],
  73. [BOTH, RAGE, /(^|\s)[мm][аa]ш[кk]/imu, "машк"],
  74. [BOTH, RAGE, /[нh][аa][вb][аa]л(яш|[ьb][нh]([оo][бдс]|ят))/imu, "навальнята"],
  75. [BOTH, RAGE, /[оo][кk][аa][тt]ыш/imu, "окатыш"],
  76. [BOTH, RAGE, /ольк[аи] из фбк/imu, "ольки из фбк"],
  77. [BOTH, RAGE, /([нh][аa][сc][рp][аa]|[xх][уy]я|(^|\s)[оo][вbнh][аa])л[ьb][нh]/imu, "ональный"],
  78. [BOTH, RAGE, /[пn][еeиu][нh][дg][оo][сc]/imu, "пиндос"],
  79. [BOTH, RAGE, /под кроватью/imu, "под кроватью"],
  80. [BOTH, RAGE, /(^|\s)[пn][оo][рp][оo][сc]/imu, "порос"],
  81. [BOTH, RAGE, /[пn][оo][рp][оo][хx][оo](?![вм])/imu, "порохобот"],
  82. [BOTH, RAGE, /(^|\s)[пn]я[тt][аa][кk]/imu, "пятак"],
  83. [BOTH, RAGE, /(^|\s)[рp][аaоo]г[уy]л/imu, "рагуль"],
  84. [BOTH, RAGE, /редактор\S{0,3}\s+соц\.?\s?сет/imu, "редактор"],
  85. [BOTH, RAGE, /[сc][вb][иuыi][нh]([еeиоoтtюя](?!н)|ь?([.,\s]|$))/imu, "свинявый"],
  86. [BOTH, RAGE, /[сc][иuыi][сc][ьb][кk]\S{4,}/imu, "сиськобот"],
  87. [BOTH, RAGE, /(^|\s|под)[сc][иu][сc]я(ль)?[нh]+(?!д)/imu, "сисян"],
  88. [BOTH, RAGE, /[сc][рp]ы[нh][оoь]?[кkч]/imu, "срыночек"],
  89. [BOTH, RAGE, /сшашк/imu, "сшашка"],
  90. [BOTH, RAGE, /[тt][аa][рp][аa][сc]/imu, "тарас"],
  91. [BOTH, RAGE, /[уy][кk][рp][оo][пn]/imu, "укроп"],
  92. [BOTH, RAGE, /(([уy][сc]|[кk][оo][пn])[рp]у?[аaоo]|\S[аaиоoуy][рp][уyоo]|[уy][рp][кk][аa])(и[нh]|нд)/imu, "усраина"],
  93. [BOTH, RAGE, /[хx][аиоaoui][хx][оoi]?л/imu, "хахлы"],
  94. [BOTH, RAGE, /[хx][рp][юя][вbкkнhрpсcшю]/imu, "хрю"],
  95. [BOTH, RAGE, /ч[уy][б6][аa][тt]/imu, "чубатый"],
  96. [BOTH, RAGE, /(^|\s)шв[яи]т/imu, "швятая"],
  97. [HEAD, RAGE, /[Н,н,H][o,о]в[o,о][р,p][o,о][c,с]/imu, "крымодебилы"]
  98. ];
  99. // ============[КОНЕЦ НАСТРОЕК]============
  100.  
  101. var clicksArray = [];
  102. var clicksTaskActive = 0;
  103. var timeoutID;
  104.  
  105. const displayBlock = document.getElementById("fullscreen-container");
  106. const title = document.title;
  107. const pager = document.getElementsByClassName("pager")[0];
  108. const inputListener = () => { delayClicksAfterUserInput(event.target, event.button); };
  109.  
  110. if (!document.URL.includes("res")) {
  111. hideOpPosts();
  112. hidePosts(0);
  113.  
  114. if (pager.style.display == "") { return; }
  115.  
  116. var callback = function(mutationsList, observer) {
  117. for(let m of mutationsList) {
  118. if (!m.addedNodes.length || m.addedNodes[0].tagName != "DIV" || m.addedNodes[0].className != "thread") { continue; }
  119.  
  120. hideOpPosts(m.addedNodes[0].firstChild.firstChild);
  121. for (let i = 1; i < m.addedNodes[0].childNodes.length; i++) {
  122. hidePosts(0, m.addedNodes[0].childNodes[i].firstChild.firstChild);
  123. }
  124. }
  125. };
  126.  
  127. var observer = new MutationObserver(callback);
  128. observer.observe(document.getElementById('posts-form'), { attributes: false, childList: true, subtree: false });
  129. } else {
  130. var hideTotalSpan = document.createElement("span");
  131. hideTotalSpan.className = "post__anon";
  132. var opPostEnd = document.getElementsByClassName("post post_type_oppost")[0].childNodes[1];
  133. hideTotalSpan = opPostEnd.insertBefore(hideTotalSpan, opPostEnd.childNodes[opPostEnd.childNodes.length - 2]);
  134.  
  135. var hiddenCount = 0;
  136. hidePosts(1);
  137.  
  138. var callback = function(mutationsList, observer) {
  139. for(let m of mutationsList) {
  140. if (!m.addedNodes.length || m.addedNodes[0].tagName != "DIV" || m.addedNodes[0].className != "" || m.addedNodes[0].firstChild.className != "thread__post") { continue; }
  141. hidePosts(1, m.addedNodes[0].firstChild.firstChild);
  142. }
  143. };
  144.  
  145. var observer = new MutationObserver(callback);
  146. observer.observe(document.getElementsByClassName('thread')[0], { attributes: false, childList: true, subtree: false });
  147. }
  148.  
  149. function hideOpPosts(node) {
  150. var opPost,
  151. opPostTitle,
  152. opPostMsg,
  153. found,
  154. opPostsCollection = [];
  155.  
  156. if (node) { opPostsCollection.push(node); }
  157. else { opPostsCollection = document.getElementsByClassName("post post_type_oppost"); }
  158.  
  159. for (let i = 0; i < opPostsCollection.length; i++) {
  160. opPost = opPostsCollection[i];
  161. if (opPost.parentNode.parentNode.style.display == "none") { continue; }
  162.  
  163. let opPostTitleText = "";
  164. let msgText = "";
  165. if ((opPostTitle = opPost.getElementsByClassName("post__title")).length) { opPostTitleText = opPostTitle[0].textContent.trim(); }
  166. if ((opPostMsg = opPost.getElementsByClassName("post__message post__message_op")).length) { msgText = opPostMsg[0].innerText.trim(); }
  167. else if (!opPostTitleText) { continue; }
  168.  
  169. found = -1;
  170. for (let j = 0; j < regexArray.length; j++) {
  171. if (opPostTitleText && regexArray[j][0] > 1 && regexArray[j][2].test(opPostTitleText)) {
  172. found = j;
  173. break;
  174. } else if (msgText && regexArray[j][0] < 3 && regexArray[j][2].test(msgText)) {
  175. found = j;
  176. break;
  177. }
  178. }
  179. if (found > -1) {
  180. if (regexArray[found][1] < 3) { requestDislike(opPost); }
  181. if (regexArray[found][1] > 1) {
  182. let hideDiv = document.createElement("div");
  183. hideDiv.className = "thread thread_hidden";
  184. if (msgText.length > 500) { hideDiv.title = msgText.substring(0, 500) + "..."; }
  185. else { hideDiv.title = msgText; }
  186.  
  187. let divPostDetailsSpans = opPost.getElementsByClassName("post__detailpart");
  188. hideDiv.innerHTML = "Скрытый тред (" + opPostTitleText + ") • hide: " + regexArray[found][3] + " " + divPostDetailsSpans[divPostDetailsSpans.length - 1].innerHTML;
  189. opPost.parentNode.parentNode.parentNode.insertBefore(hideDiv, opPost.parentNode.parentNode);
  190. opPost.parentNode.parentNode.style.display = "none";
  191. }
  192. }
  193. }
  194. }
  195.  
  196. function hidePosts(inThread, node) {
  197. var post,
  198. postTitle,
  199. postMsg,
  200. found,
  201. postsCollection = [];
  202.  
  203. if (node) { postsCollection.push(node); }
  204. else { postsCollection = document.getElementsByClassName("post post_type_reply"); }
  205.  
  206. if (postsCollection) {
  207. for (let i = 0; i < postsCollection.length; i++) {
  208. post = postsCollection[i];
  209. if (post.className == "post post_type_reply post_type_hidden") { continue; }
  210.  
  211. if (highlight && !node) { highlightPosts(post); }
  212.  
  213. found = -1;
  214. let postTitleText = "";
  215. if ((postTitle = post.getElementsByClassName("post__title")).length && (postTitleText = postTitle[0].textContent.trim())) {
  216. for (let j = 0; j < regexArray.length; j++) {
  217. if (regexArray[j][0] > 1 && regexArray[j][2].test(postTitleText)) {
  218. found = j;
  219. break;
  220. }
  221. }
  222. }
  223.  
  224. let msgText = "";
  225. if (found == -1) {
  226. if ((postMsg = post.getElementsByClassName("post__message")).length && (msgText = postMsg[0].innerText.trim())) {
  227. for (let j = 0; j < regexArray.length; j++) {
  228. if (regexArray[j][0] < 3 && regexArray[j][2].test(msgText)) {
  229. found = j;
  230. break;
  231. }
  232. }
  233. if (found > -1 && ignoreQuotes) { //double check posts
  234. msgText = postMsg[0].innerHTML;
  235. msgText = msgText.replace(/<a href=.*?<\/a>|<\/?strong>|<\/?em>|<\/?su[bp]>|<span class="[suo](poiler)?">/g, "");
  236. msgText = msgText.replace(/<br>/g, " ");
  237.  
  238. let splitStart = -1;
  239. while ((splitStart = msgText.indexOf("<span class=\"unkfunc\">")) > -1 ) {
  240. msgText = msgText.substring(0, splitStart) + msgText.substring(msgText.indexOf("</span>", splitStart + 22) + 7);
  241. }
  242. msgText = msgText.replace(/<\/span>/g, "");
  243. found = -1;
  244. for (let j = 0; j < regexArray.length; j++) {
  245. if (regexArray[j][0] < 3 && regexArray[j][2].test(msgText)) {
  246. found = j;
  247. break;
  248. }
  249. }
  250. }
  251. }
  252. }
  253.  
  254. if (found > -1) {
  255. if (regexArray[found][1] < 3) { requestDislike(post); }
  256. if (regexArray[found][1] > 1) {
  257. let hideSpan = document.createElement("span");
  258. hideSpan.className = "post__anon";
  259. if (ignoreQuotes && postMsg.length) { msgText = postMsg[0].innerText.trim(); }
  260. if (msgText.length > popupChars) { hideSpan.title = msgText.substring(0, popupChars) + "..."; }
  261. else { hideSpan.title = msgText; }
  262. hideSpan.textContent = "• hide: " + regexArray[found][3];
  263.  
  264. post.getElementsByClassName("post__details")[0].insertBefore(hideSpan, post.getElementsByClassName("turnmeoff")[1]);
  265. post.className = "post post_type_reply post_type_hidden";
  266. if (inThread) { hiddenCount++; }
  267. }
  268. }
  269. }
  270. if (inThread) { hideTotalSpan.textContent = "(скрыто постов: " + String(hiddenCount) + ")"; }
  271. }
  272. }
  273.  
  274. function highlightPosts(node) {
  275. var like,
  276. dislike,
  277. likeSpan,
  278. dislikeSpan,
  279. likeCount,
  280. dislikeCount,
  281. r,
  282. c = 120;
  283.  
  284. if ((like = node.getElementsByClassName("post__detailpart post__rate post__rate_type_like")[0]) && (likeSpan = like.children[1])) {
  285. likeCount = parseInt(likeSpan.innerHTML, 10);
  286. }
  287. if ((dislike = node.getElementsByClassName("post__detailpart post__rate post__rate_type_dislike")[0]) && (dislikeSpan = dislike.children[1])) {
  288. dislikeCount = parseInt(dislikeSpan.innerHTML, 10);
  289. }
  290. if (!likeCount) { likeCount = 1; }
  291. if (!dislikeCount) { dislikeCount = 1; }
  292.  
  293. r = likeCount / dislikeCount;
  294. if (r > 1.33) {
  295. node.style.backgroundColor = 'rgba('+String(c)+',' + String(Math.min(c+r*13,250)) + ','+String(c)+',0.2)';
  296. } else if (r < 0.75) {
  297. node.style.backgroundColor = 'rgba(' + String(Math.min(c+1/r*13,250)) + ','+String(c)+','+String(c)+',0.2)';
  298. } else if (likeCount + dislikeCount > 30) {
  299. node.style.backgroundColor = 'rgba('+String(c)+','+String(c)+','+String(c+100)+',0.2)';
  300. }
  301. }
  302.  
  303. function delayClicksAfterUserInput(element, mouseButton) {
  304. if (!clicksTaskActive || !timeoutID || mouseButton != 0) { return; }
  305.  
  306. var cname = String(element.className);
  307. if (String(element.id).includes("like-count") || cname.includes("SVGAnimatedString") || cname.includes("post__rate")) {
  308. clearTimeout(timeoutID);
  309. timeoutID = setTimeout(scheduledDislike, minClickDelay + Math.random() * (maxClickDelay - minClickDelay));
  310. }
  311. }
  312.  
  313. function requestDislike(post) {
  314. var element = post.getElementsByClassName("post__detailpart post__rate post__rate_type_dislike")[0];
  315. if (element && element.className !== "post__detailpart post__rate post__rate_type_dislike post__rate_disliked") {
  316. clicksArray.push(element);
  317. if (showInTitle) { document.title = "[👎"+clicksArray.length+"] " + title; }
  318. if (clicksTaskActive == 0) {
  319. clicksTaskActive = 1;
  320. document.addEventListener("click", inputListener);
  321. timeoutID = setTimeout(scheduledDislike, minClickDelay + Math.random() * (maxClickDelay - minClickDelay));
  322. }
  323. }
  324. }
  325.  
  326. function scheduledDislike() {
  327. if (displayBlock.style.display == "block") {
  328. timeoutID = setTimeout(scheduledDislike, 1000);
  329. return;
  330. }
  331.  
  332. timeoutID = 0;
  333. var element = clicksArray.shift();
  334. element.click();
  335. element.parentNode.parentNode.className = "post post_type_reply post_type_hidden";
  336. if (clicksArray.length) {
  337. if (showInTitle) { document.title = "[👎"+clicksArray.length+"] " + title; }
  338. timeoutID = setTimeout(scheduledDislike, minClickDelay + Math.random() * (maxClickDelay - minClickDelay));
  339. } else {
  340. document.title = title;
  341. clicksTaskActive = 0;
  342. document.removeEventListener("click", inputListener);
  343. }
  344. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement