Don't Seizi "lazy"

ランキング内の「社会・政治・時事」の動画を消すだけ

  1. // ==UserScript==
  2. // @name Don't Seizi "lazy"
  3. // @namespace https://github.com/segabito/
  4. // @version 0.4.0
  5. // @description ランキング内の「社会・政治・時事」の動画を消すだけ
  6. // @author segabito macmoto
  7. // @match *://www.nicovideo.jp/ranking*
  8. // @grant none
  9. // @run-at document-body
  10. // @noframes
  11. // ==/UserScript==
  12. (function() {
  13. if (!document.body.classList.contains('MatrixRanking-body')) {
  14. return;
  15. }
  16. const css = `
  17. [data-genre-name="society_politics_news"] {
  18. visibility: hidden;
  19. pointer-events: none;
  20. user-select: none;
  21. }
  22. `;
  23. const addStyle = function(styles, id) {
  24. const elm = document.createElement('style');
  25. elm.type = 'text/css';
  26. if (id) { elm.id = id; }
  27.  
  28. var text = styles.toString();
  29. text = document.createTextNode(text);
  30. elm.appendChild(text);
  31. document.documentElement.append(elm);
  32. return elm;
  33. };
  34.  
  35. const dateToString = date => {
  36. if (typeof date === 'string') {
  37. const origDate = date;
  38. date = date.replace(/\//g, '-');
  39. // 時差とか考慮してない
  40. const m = /^(\d+-\d+-\d+) (\d+):(\d+):(\d+)/.exec(date);
  41. if (m) {
  42. date = new Date(m[1]);
  43. date.setHours(m[2]);
  44. date.setMinutes(m[3]);
  45. date.setSeconds(m[4]);
  46. } else {
  47. const t = Date.parse(date);
  48. if (isNaN(t)) {
  49. return origDate;
  50. }
  51. date = new Date(t);
  52. }
  53. } else if (typeof date === 'number') {
  54. date = new Date(date);
  55. }
  56. if (!date || isNaN(date.getTime())) {
  57. return '1970/01/01 00:00:00';
  58. }
  59.  
  60. let [yy, mm, dd, h, m, s] = [
  61. date.getFullYear(),
  62. date.getMonth() + 1,
  63. date.getDate(),
  64. date.getHours(),
  65. date.getMinutes(),
  66. date.getSeconds()
  67. ].map(n => n.toString().padStart(2, '0'));
  68. return `${yy}/${mm}/${dd} ${h}:${m}:${s}`;
  69. };
  70.  
  71. const parseItem = item => {
  72. const id = item.querySelector('link').textContent.replace(/^.+\//, '');
  73. let watchId = id;
  74. const guid = item.querySelector('guid').textContent;
  75. const desc = new DOMParser().parseFromString(item.querySelector('description').textContent, 'text/html');
  76. const [min, sec] = desc.querySelector('.nico-info-length').textContent.split(':');
  77. const dt = guid.match(/,([\d]+-[\d]+-[\d]+):/)[1];
  78. const tm = desc.querySelector('.nico-info-date').textContent.replace(/[:]/g, ':').match(/([\d]+:[\d]+:[\d]+)/)[0];
  79. const date = new Date(`${dt} ${tm}`);
  80. const thumbnail_url = desc.querySelector('.nico-thumbnail img').src;
  81. const vm = thumbnail_url.match(/(\d+)\.(\d+)/);
  82. if (vm && /^\d+$/.test(id)) {
  83. watchId = `so${vm[1]}`;
  84. }
  85.  
  86. const result = {
  87. _format: 'nicorss',
  88. id: watchId,
  89. uniq_id: id,
  90. title: item.querySelector('title').textContent,
  91. length_seconds: min * 60 + sec * 1,
  92. thumbnail_url,
  93. first_retrieve: dateToString(date),
  94. description: desc.querySelector('.nico-description').textContent
  95. };
  96. if (desc.querySelector('.nico-info-total-res')) {
  97. Object.assign(result, {
  98. num_res: parseInt(desc.querySelector('.nico-info-total-res').textContent.replace(/,/g, ''), 10),
  99. mylist_counter: parseInt(desc.querySelector('.nico-info-total-mylist').textContent.replace(/,/g, ''), 10),
  100. view_counter: parseInt(desc.querySelector('.nico-info-total-view').textContent.replace(/,/g, ''), 10)
  101. });
  102. }
  103. return result;
  104. };
  105.  
  106. const load = url => {
  107. return fetch(url).then(r => r.text()).then(rssText => {
  108. const xml = new DOMParser().parseFromString(rssText, 'application/xml');
  109. const items = Array.from(xml.querySelectorAll('item')).map(i => parseItem(i));
  110. return {
  111. title: xml.querySelector('title').textContent,
  112. items
  113. }
  114. });
  115. };
  116.  
  117. /**
  118. *
  119. * @param {string} genre
  120. * @param {'hour'|'24h'||'week'|'month'|'total'} term
  121. * @param {string} tag
  122. * @returns ItemData[]
  123. */
  124. const loadRanking = ({genre = 'all', term = 'hour', tag = ''}) => {
  125. const url = `https://www.nicovideo.jp/ranking/genre/${genre}?term=${term}${tag ? `&tag=${encodeURIComponent(tag)}` : ''}&rss=2.0`;
  126. return load(url);
  127. };
  128.  
  129. const itemPromise = loadRanking({genre: 'society_politics_news'});
  130. addStyle(css);
  131.  
  132. const onload = async function() {
  133. const items = (await itemPromise).items;
  134. if (!items.length) {
  135. return;
  136. }
  137. const watchIds = items.map(item => item.id);
  138.  
  139.  
  140. const onItemInview = item => {
  141. const link = item.querySelector('.Card-link');
  142. const href = link.href;
  143. const match = href.match(/\watch\/([a-z0-9]+)/);
  144. if (match && watchIds.includes(match[1])) {
  145. item.dataset.genreName = 'society_politics_news';
  146. return true;
  147. }
  148. return false;
  149. };
  150.  
  151. const intersectionObserver = new window.IntersectionObserver(entries => {
  152. entries.filter(entry => entry.isIntersecting).forEach(entry => {
  153. const item = entry.target;
  154. intersectionObserver.unobserve(item);
  155. onItemInview(item);
  156. });
  157. });
  158.  
  159.  
  160. const onUpdate = target => {
  161. const items = (target || document).querySelectorAll('.RankingBaseItem:not(.is-dsl-watching)');
  162. if (!items.length) { return; }
  163. Array.from(items).forEach(item => {
  164. item.classList.add('is-dsl-watching');
  165. if (!onItemInview(item)) {
  166. intersectionObserver.observe(item);
  167. }
  168. });
  169. };
  170.  
  171. const mutationObserver = new window.MutationObserver(mutations => {
  172. if (mutations.some(mutation => mutation.addedNodes && mutation.addedNodes.length > 0)) {
  173. onUpdate(mutations.target);
  174. }
  175. });
  176.  
  177. Array.from(document.querySelectorAll('.RankingMatrixVideosRow')).forEach(container => {
  178. mutationObserver.observe(container, {childList: true, characterData: false, attributes: false, subtree: false});
  179. });
  180.  
  181. onUpdate();
  182. };
  183.  
  184. window.addEventListener('DOMContentLoaded', onload);
  185.  
  186. })();

QingJ © 2025

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