youtube channel video fliter/search demo

Simpler to find songs and singing videos in the vtuber streaming channel.

  1. // ==UserScript==
  2. // @name youtube channel video fliter/search demo
  3. // @description Simpler to find songs and singing videos in the vtuber streaming channel.
  4. // @namespace ytb_channel_video_fliter
  5. // @author Covenant
  6. // @version 1.0.5
  7. // @license MIT
  8. // @homepage
  9. // @match https://www.youtube.com/channel/*/videos*
  10. // @match https://www.youtube.com/channel/*/streams*
  11. // @match https://www.youtube.com/c/*/videos*
  12. // @match https://www.youtube.com/c/*/streams*
  13. // @match https://www.youtube.com/@*/videos*
  14. // @match https://www.youtube.com/@*/streams*
  15. // @match https://www.youtube.com/user/*/videos*
  16. // @match https://www.youtube.com/user/*/streams*
  17. // @match https://www.youtube.com/feed/subscriptions*
  18. // @icon data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAD///8AEiP//xIj//8SI///EyP//xIj//8SI///EiP//xIj//8SI///EyP//xIj//8SI///EiP//xIj//////8AEiP//wAc7v8AHO7/AB3v/wAc7v8AHO7/ABzu/wAc7v8AHO7/ABzu/wAd7/8AHe//ABzu/wAc7/8AHe//EiP//xIj//8SI////////09V//+6uv////////////9PVf//z87///////+ysv//EiP//5ub////////0tH//xIj//8SI///EiP///////9PVf///////xIj////////T1X///////8SI////////5qZ////////EiP//xIj//8TI///EiP//xIj////////T1X///////8TI////////09V////////EiP///////+amf/////////////S0f//EiP//xIj//8SI////////09V////////EiL///////9PVf////////////+6uv//EiP//7q6///v8P//0tH//xIj//8SI///EyP///////8SI///EiP//xIj//8SI///EiP///////8SI///EiP//xIj//8SI///EiP//xIj//8SI///EiP//////////////////xIj//8SI///EiP//xMj////////EiP//xIj//8SI///EiP//xIj//8SI///EiP//9nZ//8SI///EiP//xMj//8SI///EiP//xIj//8SI///EiP//xIj//8SI///EiP//xIj//8SI///EiL//9na//////////////////////////////////////////////////////////////////////////////////////////////////+r5/b/AAAA//372P//////R5K5/wAAAP/IiWb//////26v1f8AAAD/rGZE////////////////////////////qub1/wAAAP/+/Nj/qub2/wAAAP//////AAAA//782P8TcJ3//vzY/wAAAP///////////////////////////6rm9f8AAAD//vzY/6rm9v8AAAD//////wAAAP/+/Nj/AAAA//////8AAAD///////////////////////////9ur9b/AAAA/+PFov//////R5K6/wAAAP/JiWb//////wAAAP//////AAAA////////////////////////////AAAA//+p7/8AAAD/////////////////////////////////////////////////////////////////bq7V/wxKf///////rGZE/+PFov//////////////////////////////////////////////////////gAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  19. // @grant GM_setValue
  20. // @grant GM_getValue
  21. // @grant GM_registerMenuCommand
  22. // @connect
  23. // @run-at document-end
  24. // @noframes
  25. // ==/UserScript==
  26. var div_fixed;
  27. var btn_print;
  28. var input_sec;
  29. var input_word;
  30. var p_console_log;
  31. var panel_ytb=GM_getValue('panel_ytb',true);
  32. var is_enable=GM_getValue('is_enable',true);
  33. function create_style(textContent,id,class_name){
  34. let style=create_node("style",class_name,true,document.body);
  35. style.type='text/css';
  36. style.id=id;
  37. style.textContent=textContent;
  38. return style;
  39. }
  40. const font_family_panel_important="font-family: 'Noto Sans Mono','Noto Mono','Cascadia Mono','Consolas','DroidSans_Mono','Courier New','symbol_emoji','color_emoji','Noto Sans CJK JP','Meiryo','Yu Gothic','Microsoft JhengHei','old_emoji',sans-serif !important;";
  41. const font_family_default="font-family: 'Noto Sans','Segoe UI','Roboto_2','color_emoji','Noto Sans CJK JP','Meiryo','Yu Gothic','Microsoft JhengHei','old_emoji',sans-serif;";
  42. const font_face_default=`
  43. @font-face{font-family: 'color_emoji';src: local('Twemoji Mozilla'),/*url('file:///C:/Program Files/Mozilla Firefox/fonts/TwemojiMozilla.ttf'),*/local('Noto Color Emoji'),local('Segoe UI Emoji'),local('Apple Color Emoji');
  44. @font-face{font-family: 'symbol_emoji';src: local('Segoe UI Symbol');}\n@font-face{font-family: 'old_emoji';src: local('Noto Color Emoji');}
  45. @font-face{font-family: 'DroidSans_Mono';src: local('DroidSansMono');}\n@font-face{font-family: 'Cutive_Mono';src: local('Cutive Mono');}
  46. @font-face{font-family: 'Roboto_2';src: local('Roboto');}\n@font-face{font-family: 'Noto_Serif';src: local('NotoSerif');}\n@font-face{font-family: 'Dancing_Script';src: local('DancingScript');}\n`;
  47. var style_font_face=create_style(font_face_default,"gm_font_face_ytb_channel_video_fliter_demo",["user_gm_font_face","css_ytb_channel_video_fliter_demo"]);
  48. var style_user_css=create_style(".user_input_fixed,.user_btn_panel_fixed,.p_console_log{"+font_family_panel_important+"font-weight: 300;}\n","gm_user_css_ytb_channel_video_fliter_demo",["user_gm_css","css_ytb_channel_video_fliter_demo"]);
  49. style_user_css.textContent+=`input.user_input_fixed{width: auto;max-width: 95%;border-radius: 0.5rem;padding: 0.25em;}
  50. .user_input_fixed,.user_btn_panel_fixed{font-size: 120%;}
  51. .input_font_family{min-width: 90%;}\ndiv.div_br{width: 100%;}
  52. .user_div_fixed_ytb{position:fixed !important;z-index: 65535;top: 30%;right: 0px;font-size: 1.5rem;}
  53. .user_div_fixed_ytb{background: #00000033;display: flex;justify-content: flex-end;flex-wrap: wrap;min-width: 32rem;}\ndiv.div_br{width: 100%;}
  54. .user_btn_margin{margin-right: 2px;margin-left: 3px;margin-top: 1px;margin-bottom: 1px;padding-left: 5px;padding-right: 5px;}
  55. .user_btn_panel_fixed{min-width: 5em;min-height: 1em;max-height: 2em;}
  56. .display_none,#gm_css.display_none{display: none !important;}\n.display_none_fixed_ytb{display: none;}\n`;
  57. function create_div(class_name,is_appendChild,node,refNode){
  58. let div=create_node("div",class_name,is_appendChild,node,refNode);
  59. div.style.backgroundSize='contain';
  60. div.style.backgroundRepeat='no-repeat';
  61. div.lang='ja';
  62. return div;
  63. }
  64. function create_btn(innerText,class_name,is_appendChild,node,refNode){
  65. let btn=create_node_text("button",innerText,class_name,is_appendChild,node,refNode);
  66. return btn;
  67. }
  68. function create_input(placeholder,class_name,is_num,is_appendChild,node,refNode){
  69. let input=create_node("Input",class_name,is_appendChild,node,refNode);
  70. input.placeholder=placeholder;
  71. input.type="text";
  72. input.title=placeholder;
  73. if(is_num)input.size="15";
  74. if(is_num)input.setAttribute("maxlength", "10");
  75. if(is_num)input.setAttribute("oninput","this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\\..*?)\\..*/g, '$1');");
  76. return input;
  77. }
  78. function create_node(tagname,class_name,is_appendChild,node,refNode){
  79. let element=document.createElement(tagname);
  80. if(Array.isArray(class_name)){
  81. for(let i=0; i<class_name.length; i++){element.classList.add(class_name[i]);}
  82. }else if(typeof class_name==='string'){element.classList.add(class_name);}
  83. if(is_appendChild){node.appendChild(element);}else{node.insertBefore(element, refNode);}
  84. return element;
  85. }
  86. function create_node_text(tagname,innerText,class_name,is_appendChild,node,refNode){
  87. let element = create_node(tagname,class_name,is_appendChild,node,refNode);
  88. element.innerText=innerText;
  89. element.lang='ja';
  90. return element;
  91. }
  92. function fn_url(url){
  93. let obj_url=new URL(url);
  94. let params=obj_url.searchParams;
  95. //let params=new URLSearchParams(obj_url.search);
  96. return [obj_url,params];
  97. }
  98. function console_log_tmp(text,bool){
  99. let div_log=p_console_log;
  100. div_log.innerHTML+=text+" ";
  101. if(bool){div_log.innerHTML=text;}
  102. }
  103. //console.log("break");
  104. function fn_btn_print(){//press button
  105. try{
  106. var video=document.querySelectorAll('ytd-rich-item-renderer');
  107. var results=0;
  108. for(let i = 0; i < video.length; i++){
  109. let is_overlay_exist=true;
  110. let ytd_overlay_time=video[i].querySelectorAll('ytd-thumbnail-overlay-time-status-renderer');
  111. if(ytd_overlay_time.length>0){
  112. if(ytd_overlay_time[0].getAttribute("overlay-style").search(new RegExp("LIVE", "i"))!=-1){
  113. continue;//配信中(feed/subscriptions)
  114. }
  115. }else{/**/
  116. is_overlay_exist=false;
  117. }
  118. var ary_time=is_overlay_exist?video[i].querySelectorAll('span#text')[0].innerText.split(':'):["NaN"];
  119. var video_name=video[i].querySelectorAll('a>#video-title')[0].innerText;
  120. var time=0;
  121. var max_len;
  122. if(ary_time.length==1){//NaN
  123. //console_log_tmp("NaN",false);
  124. video[i].classList.remove("display_none");//配信予定, ytb_shorts
  125. }else if(ary_time.length==3){//hour
  126. time=time+parseInt(ary_time[0])*3600+parseInt(ary_time[1])*60+parseInt(ary_time[2]);
  127. }else{
  128. time=time+parseInt(ary_time[0])*60+parseInt(ary_time[1]);
  129. }
  130. //btn_print.innerHTML=btn_print.innerHTML+time+" ";
  131. if(input_sec.value==''){max_len=86400;}else{max_len=parseInt(input_sec.value)*60;}
  132. //
  133. if(is_enable)video[i].id="gm_css";//dev
  134. if(time<max_len&&video_name.search(new RegExp(input_word.value, "i"))!=-1){
  135. video[i].classList.remove("display_none");
  136. results++;
  137. }else{
  138. video[i].classList.add("display_none");
  139. }
  140. }
  141. btn_print.innerText="検索("+results+"本の動画)";
  142. }catch(e){
  143. console_log_tmp(e.message,true);
  144. }finally{}
  145.  
  146. }
  147. function fn_check_ui(){
  148. if(document.querySelectorAll('ytd-rich-item-renderer').length==0){//UI check
  149. btn_print.innerHTML="Exception";
  150. }
  151. }
  152.  
  153. (function() {
  154. 'use strict';
  155. div_fixed=create_div(["user_div_fixed_ytb"],false,document.body,document.body.firstChild);
  156. if(panel_ytb){div_fixed.classList.remove("display_none_fixed_ytb");}else{div_fixed.classList.add("display_none_fixed_ytb");}
  157. GM_registerMenuCommand('💬show input;', () => {
  158. panel_ytb=!panel_ytb;
  159. GM_setValue('panel_ytb', panel_ytb);
  160. if(panel_ytb){div_fixed.classList.remove("display_none_fixed_ytb");}else{div_fixed.classList.add("display_none_fixed_ytb");}
  161. });
  162. GM_registerMenuCommand("enable #css"+(is_enable?"✔️":"❌"), () => {
  163. is_enable=!is_enable;
  164. GM_setValue('is_enable', is_enable);
  165. });
  166. //
  167. input_sec=create_input("最大映像時間(分)/Maximum video time (minutes)",["user_input_fixed",'user_tool'],true,true,div_fixed);
  168. btn_print=create_btn("検索",["user_btn_panel_fixed","user_btn_margin",'user_tool'],true,div_fixed);
  169. create_div("div_br",true,div_fixed);
  170. p_console_log=create_node("p","p_console_log",true,div_fixed);
  171. input_word=create_input("抽出条件の指定",["user_input_fixed",'user_tool'],false,true,div_fixed);
  172. btn_print.addEventListener('click',() => {
  173. fn_btn_print();
  174. });
  175. //
  176. window.setTimeout(( () => fn_check_ui() ), 3000);////UI check need delay
  177. })();
  178. /*20221031
  179. video=document.querySelectorAll('#items>ytd-grid-video-renderer');
  180. video[i].querySelectorAll('div.badge-style-type-live-now-alternate')
  181. video[i].querySelectorAll('span#text')
  182. video[i].querySelectorAll('a#video-title')
  183. //
  184. document.querySelectorAll('#items>ytd-grid-video-renderer')
  185. */