Rllmuk Really Ignore Users

Really ignore ignored users, and ignore users in specific topics

当前为 2020-04-08 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Rllmuk Really Ignore Users
  3. // @description Really ignore ignored users, and ignore users in specific topics
  4. // @namespace https://github.com/insin/greasemonkey/
  5. // @version 6
  6. // @match https://www.rllmukforum.com/index.php*
  7. // ==/UserScript==
  8. function addStyle(css) {
  9. let $style = document.createElement('style')
  10. $style.appendChild(document.createTextNode(css))
  11. document.querySelector('head').appendChild($style)
  12. }
  13.  
  14. function TopicPage() {
  15. let topicId = document.body.dataset.pageid
  16. let ignoredUserIds = JSON.parse(localStorage.ignoredUserIds || '[]')
  17. let ignoredUsersInTopics = JSON.parse(localStorage.ignoredUsersInTopics || '{}')
  18. let topicIgnoredUserIds = []
  19. if (ignoredUsersInTopics[topicId]) {
  20. topicIgnoredUserIds = ignoredUsersInTopics[topicId].users.map(user => user.id)
  21. ignoredUserIds.push(...topicIgnoredUserIds)
  22. }
  23.  
  24. // Hide "You've chosen to ignore content by <ignored user>"
  25. addStyle(`
  26. .ipsComment_ignored {
  27. display: none;
  28. }
  29. `)
  30.  
  31. // Hide posts containing elements which have an ignored user id as a specified
  32. // data attribute.
  33. function hidePostsByDataAttribute(elements, dataAttribute) {
  34. elements.forEach(el => {
  35. if (!ignoredUserIds.includes(el.dataset[dataAttribute])) return
  36. let post = el.closest('article.ipsComment')
  37. if (post.style.display == 'none') return
  38. post.style.display = 'none'
  39. })
  40. }
  41.  
  42. // Hide posts which quote ignored users
  43. function processQuotes(context) {
  44. hidePostsByDataAttribute(
  45. context.querySelectorAll('[data-ipsquote-userid]'),
  46. 'ipsquoteUserid'
  47. )
  48. }
  49.  
  50. // Hide posts which @-mention ignored users
  51. function processMentions(context) {
  52. hidePostsByDataAttribute(
  53. context.querySelectorAll('[data-mentionid]'),
  54. 'mentionid'
  55. )
  56. }
  57.  
  58. // Hide posts by users ignored in this specific topic
  59. function processTopicIgnoredPosts(context = document) {
  60. if (topicIgnoredUserIds.length == 0) return
  61.  
  62. let postAvatarLinks = context.querySelectorAll('li.cAuthorPane_photo a')
  63. postAvatarLinks.forEach(el => {
  64. let userId = /profile\/(\d+)/.exec(el.href)[1]
  65. if (!topicIgnoredUserIds.includes(userId)) return
  66. let post = el.closest('article.ipsComment')
  67. if (post.style.display == 'none') return
  68. post.style.display = 'none'
  69. })
  70. }
  71.  
  72. // Hide the unread comment separator if all subsequent posts are hidden
  73. function updateUnreadCommentSeparator() {
  74. let separator = document.querySelector('hr.ipsCommentUnreadSeperator')
  75. if (!separator) return
  76. let hasVisiblePost = false
  77. let sibling = separator.nextElementSibling
  78. while (sibling) {
  79. if (sibling.matches('article.ipsComment') &&
  80. !sibling.classList.contains('ipsHide') &&
  81. sibling.style.display != 'none') {
  82. hasVisiblePost = true
  83. break
  84. }
  85. sibling = sibling.nextElementSibling
  86. }
  87. separator.style.display = hasVisiblePost ? '' : 'none'
  88. }
  89.  
  90. // Process all posts on the current page
  91. function processPosts(context = document) {
  92. processQuotes(context)
  93. processMentions(context)
  94. processTopicIgnoredPosts(context)
  95. }
  96.  
  97. // Process initial posts
  98. processPosts()
  99. updateUnreadCommentSeparator()
  100.  
  101. // Add a new control to a user's hover card to ignore them in this topic
  102. function processHoverCard($el) {
  103. if (!$el.classList.contains('ipsHovercard')) return
  104.  
  105. // Create a new "Topic Ignore" control
  106. let $topicIgnoreItem = document.createElement('li')
  107. $topicIgnoreItem.innerHTML = `<a href="#">
  108. <i class="fa fa-times-circle"></i> Topic Ignore
  109. </a>`
  110. let $ignoreLink = $topicIgnoreItem.querySelector('a')
  111. $ignoreLink.addEventListener('click', (e) => {
  112. e.preventDefault()
  113.  
  114. let topicName = document.querySelector('.ipsType_pageTitle').innerText
  115. let user = {
  116. id: /profile\/(\d+)/.exec($el.querySelector('a').href)[1],
  117. name: $el.querySelector('h2').innerText,
  118. avatar: $el.querySelector('img.ipsUserPhoto').src,
  119. }
  120.  
  121. // Add the user to the ignored users config for this topic
  122. let ignoredUsersInTopics = JSON.parse(localStorage.ignoredUsersInTopics || '{}')
  123. if (ignoredUsersInTopics[topicId] == undefined) {
  124. ignoredUsersInTopics[topicId] = {
  125. name: topicName,
  126. users: [],
  127. }
  128. }
  129. ignoredUsersInTopics[topicId].name = topicName
  130. ignoredUsersInTopics[topicId].users.push(user)
  131. localStorage.ignoredUsersInTopics = JSON.stringify(ignoredUsersInTopics)
  132.  
  133. // Apply the new ignored user settings
  134. ignoredUserIds.push(user.id)
  135. topicIgnoredUserIds.push(user.id)
  136. processPosts()
  137. updateUnreadCommentSeparator()
  138.  
  139. // Hide the hover card
  140. $el.style.display = 'none'
  141. })
  142.  
  143. // Insert the new control into the hover card
  144. let $findContentItem = $el.querySelector('ul.ipsList_inline li:last-child')
  145. $findContentItem.parentNode.insertBefore($topicIgnoreItem, $findContentItem)
  146. }
  147.  
  148. // Watch for posts being replaced when paging
  149. new MutationObserver(mutations =>
  150. mutations.forEach(mutation => {
  151. if (mutation.oldValue == 'true') {
  152. processPosts()
  153. updateUnreadCommentSeparator()
  154. }
  155. })
  156. ).observe(document.querySelector('div.cTopic'), {
  157. attributes: true,
  158. attributeFilter: ['animating'],
  159. attributeOldValue: true,
  160. })
  161.  
  162. // Watch for new posts being loaded into the current page
  163. new MutationObserver(mutations => {
  164. mutations.forEach(mutation =>
  165. mutation.addedNodes.forEach(processPosts)
  166. )
  167. updateUnreadCommentSeparator()
  168. }).observe(document.querySelector('#elPostFeed > form'), {
  169. childList: true,
  170. })
  171.  
  172. // Watch for user hover cards being added for display
  173. new MutationObserver(mutations => {
  174. mutations.forEach(mutation =>
  175. mutation.addedNodes.forEach(processHoverCard)
  176. )
  177. }).observe(document.body, {
  178. childList: true,
  179. })
  180. }
  181.  
  182. function IgnoredUsersPage() {
  183. // Sync ignored user ids
  184. localStorage.ignoredUserIds = JSON.stringify(
  185. Array.from(document.querySelectorAll('[data-ignoreuserid]')).map(el =>
  186. el.dataset.ignoreuserid
  187. )
  188. )
  189.  
  190. // Add a new section to manage users ignored in specific topics
  191. let $mainArea = document.querySelector('#ipsLayout_mainArea')
  192. $mainArea.appendChild(document.createElement('br'))
  193. let $div = document.createElement('div')
  194. $div.className = 'ipsBox'
  195.  
  196. function populateIgnoredUsersInTopics() {
  197. let ignoredUsersInTopics = JSON.parse(localStorage.ignoredUsersInTopics || '{}')
  198.  
  199. $div.innerHTML = `
  200. <h2 class="ipsType_sectionTitle ipsType_reset ipsClear">Users currently being ignored in specific topics</h2>
  201. <ol class="ipsDataList ipsGrid ipsGrid_collapsePhone ipsClear" data-role="tableRows">
  202. </ol>`
  203. let $ol = $div.querySelector('ol')
  204.  
  205. if (Object.keys(ignoredUsersInTopics).length == 0) {
  206. $ol.innerHTML = `<li class="ipsDataItem">
  207. <div class="ipsType_light ipsType_center ipsPad">
  208. <br>
  209. <br>
  210. You're not currently ignoring any users in specific topics.
  211. </div>
  212. </li>`
  213. }
  214.  
  215. for (let [topicId, topicConfig] of Object.entries(ignoredUsersInTopics)) {
  216. for (let user of topicConfig.users) {
  217. let $li = document.createElement('li')
  218. $li.className = 'ipsDataItem ipsGrid_span6 ipsFaded_withHover'
  219. $li.innerHTML = `
  220. <p class="ipsType_reset ipsDataItem_icon">
  221. <a href="https://www.rllmukforum.com/index.php?/profile/${user.id}" class="ipsUserPhoto ipsUserPhoto_tiny">
  222. <img src="${user.avatar}" alt="${user.name}">
  223. </a>
  224. </p>
  225. <div class="ipsDataItem_main">
  226. <h4 class="ipsDataItem_title"><strong>${user.name}</strong></h4>
  227. <ul class="ipsList_inline">
  228. <li class="ipsType_light">
  229. in <a href="https://www.rllmukforum.com/index.php?/topic/${topicId}">
  230. ${topicConfig.name}
  231. </a>
  232. </li>
  233. <li>
  234. <a href="#" class="unignore ipsPos_middle ipsType_blendLinks">
  235. <i class="fa fa-times-circle"></i> Stop ignoring
  236. </a>
  237. </li>
  238. </ul>
  239. </div>`
  240. $li.querySelector('a.unignore').addEventListener('click', (e) => {
  241. e.preventDefault()
  242. let ignoredUsersInTopics = JSON.parse(localStorage.ignoredUsersInTopics || '{}')
  243. if (!ignoredUsersInTopics[topicId]) return populateIgnoredUsersInTopics()
  244. let index = ignoredUsersInTopics[topicId].users.findIndex(u => u.id == user.id)
  245. if (index == -1) return populateIgnoredUsersInTopics()
  246. ignoredUsersInTopics[topicId].users.splice(index, 1)
  247. if (ignoredUsersInTopics[topicId].users.length == 0) {
  248. delete ignoredUsersInTopics[topicId]
  249. }
  250. localStorage.ignoredUsersInTopics = JSON.stringify(ignoredUsersInTopics)
  251. populateIgnoredUsersInTopics()
  252. })
  253. $ol.appendChild($li)
  254. }
  255. }
  256.  
  257. $mainArea.appendChild($div)
  258. }
  259.  
  260. populateIgnoredUsersInTopics()
  261. }
  262.  
  263. let page
  264. if (location.href.includes('index.php?/topic/')) {
  265. page = TopicPage
  266. } else if (location.href.includes('index.php?/ignore/')) {
  267. page = IgnoredUsersPage
  268. }
  269.  
  270. if (page) {
  271. page()
  272. }