少数派屏蔽用户

请自行编辑屏蔽列表 blockedUsers,内容为用户主页地址,比如 https://sspai.com/u/vistaing/updates 中的 vistaing

  1. // ==UserScript==
  2. // @name 少数派屏蔽用户
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.2
  5. // @description 请自行编辑屏蔽列表 blockedUsers,内容为用户主页地址,比如 https://sspai.com/u/vistaing/updates 中的 vistaing
  6. // @author duckmouse
  7. // @match https://sspai.com/
  8. // @match https://sspai.com/post/*
  9. // @match https://sspai.com/t/*
  10. // @match https://sspai.com/community
  11. // @match https://sspai.com/community/*
  12. // @run-at document-end
  13. // @icon https://www.google.com/s2/favicons?sz=64&domain=sspai.com
  14. // @grant unsafeWindow
  15. // @grant GM_getValue
  16. // @grant GM_setValue
  17. // @grant GM_registerMenuCommand
  18. // @license WTFPL
  19. // ==/UserScript==
  20.  
  21. (async function() {
  22. 'use strict';
  23. // TODO: article tag, emoji reaction
  24.  
  25. const blockedUsers=new Set(GM_getValue('list',['tgwbddu0','5ayuq8jn','feverlife','o9azstw9','9hde6zq2','1ulv3hnm','4ea7t2zo','kiens',]))
  26. console.log('blocking users:',[...blockedUsers])
  27.  
  28. GM_registerMenuCommand('配置屏蔽用户',()=>{
  29. const oldList=GM_getValue('list',[...blockedUsers])
  30. const input=prompt('请输入用户的主页地址,以逗号分隔',oldList.join(','))
  31. const list=input.split(',').map(s=>s.split(',')).flat()
  32. GM_setValue('list',list)
  33. alert('刷新后生效')
  34. })
  35.  
  36.  
  37. await waitFor(mounted)
  38.  
  39. const vue=unsafeWindow.$vue
  40.  
  41. filter()
  42. vue.$router.afterEach(()=>{
  43. setTimeout(filter,1000)
  44. })
  45.  
  46. function filter(){
  47. console.log('开始过滤')
  48. const routes=vue.$router.getRoutes()
  49. const homePage=routes.find(r=>r.name==='home')?.instances.default
  50. const postPage=routes.find(r=>r.name==='article')?.instances.default
  51. const communityPage=routes.find(r=>r.name==='communityTopic')?.instances.default
  52. const communityHome=routes.find(r=>r.name==='communityHome')?.instances.default
  53. const community=routes.filter(r=>r.path.startsWith('/community')).find(r=>r.name===$vue.$route.name)?.instances.default
  54.  
  55. // 首页文章列表
  56. if(homePage){
  57. homePage.$watch('articleListData', val=>{
  58. const newVal=val.filter(
  59. article=>{
  60. const shouldHide=blockedUsers.has(article.author?.slug)
  61. if(shouldHide)console.log(`blocked: ${article.title} by ${article.author.nickname}`)
  62. return !shouldHide
  63. }
  64. )
  65. if(newVal.length!==val.length) homePage.articleListData=newVal
  66. }, {immediate:true})
  67. }
  68.  
  69. // 文章页
  70. if(postPage){
  71. // 文章评论区
  72. const commentsComp=postPage.$children.map(c=>c.$children).flat(Infinity).find(c=>c.$options.name==='comment')
  73. commentsComp.$watch('comments', val=>{
  74. const newVal=val.filter(
  75. comment=>{
  76. const newReplies=comment.reply?.filter(reply=>{
  77. const shouldHide=blockedUsers.has(reply.user.slug)
  78. if(shouldHide)console.log(`blocked: ${reply.comment} by ${reply.user.nickname}`)
  79. return !shouldHide
  80. })
  81. if(newReplies.length!==comment.reply?.length)comment.reply=newReplies
  82.  
  83. const shouldHide=blockedUsers.has(comment.user?.slug)
  84. if(shouldHide)console.log(`blocked: ${comment.comment} by ${comment.user.nickname}`)
  85. return !shouldHide
  86. }
  87. )
  88. if(newVal.length!==val.length)commentsComp.comments=newVal
  89. }, {immediate:true})
  90.  
  91. // 文章作者 页面标红
  92. if(blockedUsers.has(postPage.articleInfo.author.slug))mask()
  93. }
  94.  
  95. // 社区主题内容
  96. if(communityPage){
  97. // 主题作者 页面标红
  98. if(blockedUsers.has(communityPage.userInfo.slug))mask()
  99.  
  100. // 评论
  101. communityPage.$watch('comments', val=>{
  102. const newVal=val.filter(
  103. comment=>{
  104. const newReplies=comment.reply?.filter(reply=>{
  105. const shouldHide=blockedUsers.has(reply.author.slug)
  106. if(shouldHide)console.log(`blocked: ${reply.comment} by ${reply.author.nickname}`)
  107. return !shouldHide
  108. })
  109. if(newReplies.length!==comment.reply?.length)comment.reply=newReplies
  110.  
  111. const shouldHide=blockedUsers.has(comment.author?.slug)
  112. if(shouldHide)console.log(`blocked: ${comment.comment} by ${comment.author.nickname}`)
  113. return !shouldHide
  114. }
  115. )
  116. if(newVal.length!==val.length)communityPage.comments=newVal
  117. }, {immediate:true})
  118. }
  119.  
  120. // 社区主题列表
  121. if(community){
  122. community.$watch('collection', val=>{
  123. const newVal=val.filter(
  124. topic=>{
  125. const shouldHide=blockedUsers.has(topic.author?.slug)
  126. if(shouldHide)console.log(`blocked: ${topic.title} by ${topic.author.nickname}`)
  127. return !shouldHide
  128. }
  129. )
  130. if(newVal.length!==val.length)
  131. community.$store.commit('communityChannel/setCollection',{collection:newVal})
  132. }, {immediate:true})
  133. }
  134. }
  135.  
  136. function mounted(){
  137. return unsafeWindow.$vue?._isMounted
  138. }
  139.  
  140. function waitFor(check){
  141. return new Promise(ok=>{
  142. const id=setInterval(()=>{
  143. if(check()){
  144. clearInterval(id)
  145. ok()
  146. }
  147. },1000); // 篡改猴自带的编辑器在括号后看到分号才能正常缩进下一行
  148. })
  149. }
  150.  
  151. function mask(){
  152. const div=document.createElement('div')
  153. div.style.width='100vw'
  154. div.style.height='100vh'
  155. div.style.position='fixed'
  156. div.style.top=0
  157. div.style.left=0
  158. div.style.zIndex=99 // 刚好不遮盖导航栏
  159. div.style.backgroundColor='darkred'
  160.  
  161. document.body.appendChild(div)
  162. }
  163. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址