Novel Ranking Filter [No GM_API Version]

Novel Ranking Filtering Bookmarklet for Mobile Browser

Installa questo script?
Script suggerito dall'autore

Potresti essere interessato/a anche a Novel Ranking Comments Filter

Installa questo script
  1. // ==UserScript==
  2. // @name Novel Ranking Filter [No GM_API Version]
  3. // @name:ja 小説ランキングフィルター [GM_APIなし]
  4. // @namespace https://greatest.deepsurf.us/en/users/1264733
  5. // @version 2024-06-23
  6. // @description Novel Ranking Filtering Bookmarklet for Mobile Browser
  7. // @description:ja モバイルブラウザ用小説ランキングフィルタリングブックマークレット
  8. // @author LE37
  9. // @license MIT
  10. // @include https://www.alphapolis.co.jp/novel/index*
  11. // @include https://www.alphapolis.co.jp/novel/ranking/*
  12. // @include https://kakuyomu.jp/genr*
  13. // @include https://kakuyomu.jp/pick*
  14. // @include https://kakuyomu.jp/rank*
  15. // @include https://kakuyomu.jp/sear*
  16. // @include https://kakuyomu.jp/rece*
  17. // @include https://syosetu.org/?mode=rank*
  18. // @include https://yomou.syosetu.com/rank/*
  19. // @include https://yomou.syosetu.com/search*
  20. // @exclude https://www.alphapolis.co.jp/novel/ranking/annual
  21. // @exclude https://yomou.syosetu.com/rank/top/
  22. // @grant none
  23. // ==/UserScript==
  24.  
  25. (()=>{
  26. /*LS20240623*/
  27. 'use strict';
  28. // GM key, Nodelist, userLink, userid, tag, alt;
  29. let gMk,eNo,eUl,sId,sTg,eAt;
  30. // View mode
  31. let V=false;
  32. // Current list
  33. let O,A,T;
  34. // Client type
  35. const M=navigator.userAgent.includes("Mobile");
  36. const P=location.pathname;
  37. switch(location.host){
  38. case "www.alphapolis.co.jp":
  39. gMk="A";
  40. eNo="div.section";
  41. eUl="div.author>a";
  42. sId=/detail\/(\d+)$/;
  43. sTg="li.tag a";
  44. break;
  45. case "syosetu.org":
  46. gMk="H";
  47. eNo=M?"div.search_box":"div.section3";
  48. eUl=null;
  49. sId=/:(.*)/;
  50. sTg=M?'span[id^="tag_"]':'div.all_keyword:nth-child(9) a';
  51. eAt=M?"p:nth-child(2)":"div.blo_title_sak";
  52. break;
  53. case "kakuyomu.jp":
  54. gMk="K";
  55. sId=/users\/(.*)$/;
  56. if(P.startsWith("/search")){
  57. eNo=M?'div[class*="Spacer_margin-ml-m__"]':'div[class*="NewBox_borderSize-bb"]';
  58. eUl=M?'span[class*="workLabelAuthor__"] a':"div.partialGiftWidgetActivityName>a";
  59. sTg='a[href^="/tags/"]';
  60. }else if(P.startsWith("/recent_r")){
  61. eNo="div.recentReviews-item";
  62. eUl="a.widget-workCard-authorLabel";
  63. sTg='a[href^="/tags/"]';
  64. }else{
  65. eNo="div.widget-work";
  66. eUl="a.widget-workCard-authorLabel";
  67. sTg="a[itemprop='keywords']";
  68. }
  69. break;
  70. case "yomou.syosetu.com":
  71. gMk="N";
  72. if(P.startsWith("/search")){
  73. eNo=M?"div.smpnovel_list":"div.searchkekka_box";
  74. eUl=M?null:"a:nth-child(2)";
  75. sId=M?/:(.*)/:/\/(\d+)/;
  76. sTg='a[href*="?word"]';
  77. eAt="p.author";
  78. }else{
  79. eNo="div.p-ranklist-item";
  80. eUl="div.p-ranklist-item__author a";
  81. sId=/\/(\d+)/;
  82. sTg="div.p-ranklist-item__keyword a";
  83. }
  84. break;
  85. }
  86. //console.log( {gMk, eNo, eUl, sId, sTg, eAt} );
  87. // Read list
  88. function URD(){
  89. const G=JSON.parse(localStorage.getItem(gMk));
  90. O=G?G:{AL:[],TL:[]};
  91. A=O.AL;
  92. T=O.TL;
  93. }
  94. // Save list
  95. function USV(){
  96. if(JSON.stringify(O)!==localStorage.getItem(gMk)){
  97. localStorage.setItem(gMk,JSON.stringify(O));
  98. }
  99. }
  100. // Run
  101. URD();
  102. FMD();
  103. CFB();
  104. // Filtering multiple targets
  105. function FMD(){
  106. const no=document.querySelectorAll(eNo);
  107. for(let i=0;i<no.length;i++){
  108. let rBk=false;
  109. let uId;
  110. // Filtering content contain single id(link) or text
  111. let eLk=eUl?no[i].querySelector(eUl):no[i].querySelector(eAt);
  112. if(eLk!==null||(gMk==="N"&&M)){
  113. if(!eLk){
  114. // Narou search mobile no author link
  115. if(gMk==="N"){
  116. const tca=document.createElement("p");
  117. tca.classList.add("author");
  118. tca.style.color="#fe7643";
  119. const head=no[i].querySelector("div.accordion_head");
  120. // AD
  121. if(!head){
  122. //console.log("===A D===");
  123. //rBk = true;
  124. continue;
  125. }
  126. tca.textContent=head.textContent.split("\n")[3];
  127. no[i].querySelector("a.read_button").after(tca);
  128. eLk=tca;
  129. uId=eLk.textContent.match(sId)[1];
  130. }
  131. }else{
  132. uId=eUl?eLk.href.match(sId)[1]:eLk.textContent.match(sId)[1];
  133. }
  134. //console.log(uId);
  135. rBk=CHK(eLk,"a",A,uId);
  136. }
  137. if(sTg&&!rBk){
  138. // Filtering content contain multiple tags(text)
  139. // Tag node
  140. let tno;
  141. // Hameln mobile origin tag, custom tag
  142. let tot,tct;
  143. if(gMk==="H"&&M){
  144. tot=no[i].querySelector(".trigger p:nth-child(4)");
  145. tct=no[i].querySelector(sTg);
  146. if(!tct){
  147. tno=tot.textContent.slice(3).match(/[^\s]+/g);
  148. tot.innerHTML="";
  149. }else{
  150. tno=no[i].querySelectorAll(sTg);
  151. }
  152. }else{
  153. tno=no[i].querySelectorAll(sTg);
  154. }
  155. for(let j=0;j<tno.length;j++){
  156. let tag;
  157. if(tot&&!tct){
  158. tag=tno[j];
  159. tot.innerHTML+='<span id="tag_'+j+'">'+tag+'</span>';
  160. }else{
  161. tag=tno[j].textContent;
  162. }
  163. //console.log(tag);
  164. rBk=tot&&!tct?CHK(no[i].querySelector("span#tag_"+j),"t",T,tag):CHK(tno[j],"t",T,tag);
  165. if(rBk)break;
  166. }
  167. }
  168. // Blocked show type
  169. no[i].style.display=!V&&rBk?"none":"";
  170. no[i].style.opacity=V&&rBk?"0.5":"1";
  171. }
  172. }
  173. // Check keyword
  174. function CHK(e,n,l,s){
  175. const r=l.some((v)=>s===v);
  176. if(!e.classList.contains("c_h_k")){
  177. e.classList.add("c_h_k");
  178. e.setAttribute("data-r",n+s);
  179. }
  180. if(V){
  181. e.style.border=r?"thin solid fuchsia":"thin solid dodgerblue";
  182. }else{
  183. e.style.border="none";
  184. }
  185. return r;
  186. }
  187.  
  188. // Select mode
  189. function SVM(){
  190. const bt=document.getElementById("r_fcb");
  191. if(!V){
  192. V=true;
  193. bt.textContent="📙";
  194. document.addEventListener("click",ECH);
  195. URD();
  196. }else{
  197. V=false;
  198. bt.textContent="📘";
  199. document.removeEventListener("click",ECH);
  200. // Auto save list
  201. USV();
  202. }
  203. FMD();
  204. }
  205. // Handler
  206. function ECH(e){
  207. e.preventDefault();
  208. const eT=e.target;
  209. const tE=eT.classList.contains("c_h_k")?eT
  210. :eT.parentElement.classList.contains("c_h_k")?eT.parentElement
  211. :null;
  212. //console.log(tE);
  213. if(tE){
  214. const tda=tE.getAttribute("data-r");
  215. const tlst=tda.slice(0,1)==="a"?A:T;
  216. const tid=tda.slice(1);
  217. const li=tlst.findIndex((v)=>v===tid);
  218. if(li!==-1){
  219. tlst.splice(li,1);
  220. }else{
  221. tlst.push(tid);
  222. }
  223. FMD();
  224. }
  225. }
  226.  
  227. // Update Blocklists List
  228. function UBL(){
  229. alert(gMk+":"+localStorage.getItem(gMk));
  230. }
  231. // Sort Blocklists List
  232. function SBL(){
  233. A.sort();
  234. T.sort();
  235. USV();
  236. UBL();
  237. }
  238. // Delete Block List
  239. function DBL(){
  240. const t=prompt("Delete?","No");
  241. if(t==="Yes"){
  242. localStorage.removeItem(gMk);
  243. URD();
  244. UBL();
  245. FMD();
  246. }
  247. }
  248. // Create Float Button
  249. function CFB(){
  250. BCR("r_fcb","📘","2","2");
  251. BCR("r_ubl","♻","4","2");
  252. BCR("r_dbl","📛","4","4");
  253. BCR("r_sbl","🔀","2","4");
  254. document.addEventListener("click",BLM);
  255. }
  256. function BLM(e){
  257. switch(e.target.id){
  258. case "r_fcb":
  259. SVM();
  260. break;
  261. case "r_ubl":
  262. UBL();
  263. break;
  264. case "r_dbl":
  265. DBL();
  266. break;
  267. case "r_sbl":
  268. SBL();
  269. break;
  270. }
  271. }
  272. // Button creater
  273. function BCR(id,text,x,y){
  274. const cb=document.body.appendChild(document.createElement("button"));
  275. cb.id=id;
  276. cb.textContent=text;
  277. cb.style="position:fixed;width:44px;height:44px;z-index:999;font-size:200%;opacity:50%;cursor:pointer;right:"+x+"em;bottom:"+y+"em;";
  278. cb.type="button";
  279. }
  280. })();