LZT Small Hides

removes a bunch of nicknames from hide

  1. // ==UserScript==
  2. // @name LZT Small Hides
  3. // @namespace lzt-small-hides
  4. // @version 1.0
  5. // @description removes a bunch of nicknames from hide
  6. // @author Toil
  7. // @license MIT
  8. // @match https://zelenka.guru/*
  9. // @match https://lolz.live/*
  10. // @match https://lolz.guru/*
  11. // @match https://lzt.market/*
  12. // @match https://lolz.market/*
  13. // @match https://zelenka.market/*
  14. // @icon https://www.google.com/s2/favicons?sz=64&domain=zelenka.guru
  15. // @supportURL https://zelenka.guru/toil/
  16. // @grant GM_addStyle
  17. // ==/UserScript==
  18.  
  19. (async function() {
  20. 'use strict';
  21.  
  22. // * STYLES
  23. GM_addStyle(`
  24. .LSHLink {
  25. color: rgb(148, 148, 148);
  26. cursor: pointer;
  27. }
  28. .LSHLink:hover {
  29. text-decoration: underline;
  30. }
  31. `)
  32.  
  33. // * CONSTANTS
  34. const XF_LANG = XenForo?.visitor?.language_id === 1 ? 'en' : 'ru';
  35. const timestamp = Math.floor(Date.now() / 1000);
  36. const myLink = document.querySelector('#AccountMenu > .blockLinksList > li > a')?.href?.replace(window.location.origin + '/', ''); // get link to your profile
  37.  
  38. // * I18N
  39. const i18n = {
  40. ru: {
  41. you: ' Вам',
  42. forYou: ' Вас',
  43. andMore: ' и еще ',
  44. users: 'пользователям',
  45. forUsers: 'пользователей',
  46. hiddenContent: 'Скрытый контент',
  47. hiddenContentFor: 'Скрытый контент для'
  48. },
  49. en: {
  50. you: ' You',
  51. forYou: ' You',
  52. andMore: ' and more ',
  53. users: 'users',
  54. forUsers: 'users',
  55. hiddenContent: 'Hidden content',
  56. hiddenContentFor: 'Hidden content for'
  57. },
  58. get(phrase) {
  59. return this[XF_LANG]?.[phrase] ?? phrase;
  60. },
  61. }
  62.  
  63. // * SCRIPT
  64. await XenForo.scriptLoader.loadCssAsync(['avatar_user_badge', 'member_card'], `css.php?css=__sentinel__&style=9&dir=LTR&d=${timestamp}`); // force load member card css
  65.  
  66. function formatHides(elements) {
  67. for (let hide of elements) {
  68. if (hide.children.length >= 2) {
  69. hide = hide.querySelector('.attribution.type');
  70. } else {
  71. hide = hide.querySelector('.hideContainer > .quote')
  72. }
  73.  
  74. const content = hide.innerHTML;
  75. const contentSplitted = content.split(' <a href=');
  76. const hideUsersLength = contentSplitted.length - 1;
  77.  
  78. let text = contentSplitted[0];
  79. // fix for named hides
  80. if (text === 'Hidden content for next users:' || text === 'Скрытый контент для пользователей') {
  81. text = i18n.get('hiddenContentFor');
  82. }
  83.  
  84. const usersPhrase = text === i18n.get('hiddenContentFor') ? i18n.get('forUsers') : i18n.get('users');
  85. const youPhrase = text === i18n.get('hiddenContentFor') ? i18n.get('forYou') : i18n.get('you');
  86.  
  87. if (hideUsersLength > 3) {
  88. const YouFilterString = `"${myLink}" class="username"`
  89. const formattedTextEl = document.createElement('span');
  90. const otherUsersEl = document.createElement('span');
  91. otherUsersEl.classList.add('LSHLink');
  92. otherUsersEl.onclick = async () => openUserListModal(contentSplitted.filter(a => !a.startsWith(YouFilterString)));
  93.  
  94. const youInHide = contentSplitted.find(a => a.startsWith(YouFilterString));
  95. if (youInHide) {
  96. const formattedYouEl = document.createElement('span');
  97. formattedYouEl.classList.add('LSHLink');
  98. formattedYouEl.innerText = youPhrase;
  99. formattedYouEl.onclick = async () => await openUserModal(myLink);
  100.  
  101. otherUsersEl.innerText = `${hideUsersLength - 1} ${usersPhrase}`;
  102.  
  103. formattedTextEl.append(formattedYouEl, i18n.get('andMore'));
  104. } else {
  105. otherUsersEl.innerText = ` ${hideUsersLength} ${usersPhrase}`;
  106. }
  107.  
  108. formattedTextEl.append(otherUsersEl)
  109. hide.innerHTML = '';
  110. hide.append(text, formattedTextEl, '.');
  111. }
  112. }
  113. }
  114.  
  115. async function openUserModal(userLink) {
  116. const userContent = await XenForo.ajax(`/${userLink}?card=1`)
  117. return XenForo.createOverlay(null, userContent.templateHtml).load();
  118. }
  119.  
  120. async function openUserListModal(users, title = i18n.get('hiddenContent')) {
  121. const container = document.createElement('div');
  122. const formattedUsers = users.map(a => a.startsWith('"') ? ' <a href=' + a : a);
  123. for (const formattedUser of formattedUsers) {
  124. container.innerHTML += formattedUser;
  125. }
  126. return XenForo.alert(container.innerHTML, title)
  127. }
  128.  
  129.  
  130. function init() {
  131. const hides = document.querySelectorAll(".bbCodeHide > aside");
  132. formatHides(hides);
  133. }
  134.  
  135. init();
  136.  
  137. const observer = new MutationObserver((mutationsList, observer) => {
  138. for (const mutation of mutationsList) {
  139. if (mutation.type === 'childList') {
  140. mutation.addedNodes.forEach(node => {
  141. if (node.nodeType === Node.ELEMENT_NODE) {
  142. const newHides = node.querySelectorAll('.bbCodeHide > aside');
  143. if (newHides) {
  144. formatHides(newHides);
  145. }
  146. }
  147. });
  148. }
  149. }
  150. });
  151.  
  152. const config = { childList: true, subtree: true };
  153. observer.observe(document.body, config);
  154.  
  155. })();