youtube_to_invidious.user.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // ==UserScript==
  2. // @name YouTube to Invidious
  3. // @author OdinBrood, Jesús E.
  4. // @namespace InvidiousRedirect
  5. // @description Scan page for Youtube urls and replace with Invidious.
  6. // @homepageURL https://git.sr.ht/~heckyel/book/blob/master/scripts-greasemonkey
  7. // @include *
  8. // @exclude /^http(s|)://(www[.]|)invidio[.]us/.*$/
  9. // @exclude /^http(s|)://(www[.]|proxy[.]|)invidious[.]snopyta[.]org/.*$/
  10. // @exclude /^http(s|)://(www[.]|)vid[.]wxzm[.]sx/.*$/
  11. // @exclude /^http(s|)://(www[.]|)invidious[.]kabi[.]tk/.*$/
  12. // @exclude /^http(s|)://(www[.]|)invidiou[.]sh/.*$/
  13. // @exclude /^http(s|)://(www[.]|)yewtu[.]be/.*$/
  14. // @exclude /^http(s|)://(www[.]|)invidious[.]ggc-project[.]de/.*$/
  15. // @exclude /^http(s|)://(www[.]|)invidious[.]enkirton[.]net/.*$/
  16. // @exclude /^http(s|)://(www[.]|)tube[.]poal[.]co/.*$/
  17. // @exclude /^http(s|)://(www[.]|)invidious[.]13ad[.]de/.*$/
  18. // @grant none
  19. // @version 8.4.9
  20. // @license GPL version 3 or any later version::: https://www.gnu.org/licenses/gpl-3.0.html
  21. // ==/UserScript==
  22. /* jshint esversion: 6 */
  23. // set you favorite Invidious instance! (https://github.com/omarroth/invidious/wiki/Invidious-Instances)
  24. let instance = 'invidious.13ad.de';
  25. // Console Style - Debug
  26. const consoleCSS = 'background: #000; color: #00FF00; padding: 0px 7px; border: 1px solid #00FF00; line-height: 16px;';
  27. const name = GM_info.script.name;
  28. const version = GM_info.script.version;
  29. const log = (...args) => console.log('%cUSERSCRIPT | %s %s | %s', consoleCSS, name, version, ...args);
  30. // change script options, default values recommended
  31. let a=1; //set to 0 to force autoplay off, set to 1 to keep embed's value [default 1]
  32. let b=1; //set to 0 to not replace all youtube links to Invidious [default 1]
  33. let ytdomains=new RegExp(/http(s|):\/\/(m[.]|i[.]|www[.]|img[.]|)(youtu(|be|be-nocookie)|.*ytimg)[.](com|be)\/.*/);
  34. let params=new RegExp(/^(autoplay|channel|v|playlist|list)$/);
  35. let current=window.location.href.match(ytdomains)===null;
  36. let thumbs,links,skip;
  37. function link(){
  38. for(let i=0;i<links.length;i++){
  39. let url=new URL(links[i].href.match(ytdomains)[0]);
  40. url.hostname=instance;
  41. links[i].href=url;
  42. }
  43. }
  44. function ytel(el){
  45. for(let i=0;i<el.attributes.length;i++){
  46. let val=el.attributes[i].value;
  47. if(val.substring(0,2)=='//')val='https:'+val;
  48. try{val=decodeURIComponent(val);}catch(e){}
  49. if(val.match(ytdomains)){
  50. el.attributes[i].value=val;
  51. return true;
  52. }
  53. }
  54. }
  55. function ythref(el){
  56. return(decodeURIComponent(el.href).match(ytdomains));
  57. }
  58. function thumb(){
  59. for(let i=0;i<thumbs.length;i++){
  60. let url=new URL(thumbs[i].src.match(ytdomains)[0]);
  61. url.hostname=instance;
  62. thumbs[i].src=url;
  63. }
  64. }
  65. function redir(){
  66. let url=new URL(window.location.href);
  67. url.hostname=instance;
  68. location.href=url;
  69. }
  70. function addbtn(){
  71. for(let i=0;i<title.length;i++){
  72. let btn=document.createElement('a');
  73. btn.innerHTML='<h2>Watch on '+instance+'</h2>';
  74. btn.href='javascript:void(0)';
  75. btn.onclick=function(){
  76. redir();
  77. }
  78. btn.className='skipinv';
  79. title[i].parentNode.appendChild(btn);
  80. }
  81. }
  82. if(current){
  83. thumbs=Array.prototype.slice.call(document.getElementsByTagName('img')).filter(ytel);
  84. if(b==1)links=Array.prototype.slice.call(document.getElementsByTagName('a')).filter(ythref);
  85. if(thumbs.length>0){
  86. thumb();
  87. }
  88. if(links.length>0){
  89. link();
  90. }
  91. log('successfully initialized');
  92. }else{
  93. let title=Array.prototype.slice.call(document.getElementsByTagName('h1'));
  94. addbtn();
  95. }
  96. let observer=new MutationObserver(function(mutations){
  97. mutations.forEach(function(mutation){
  98. if(current){
  99. thumbs=Array.prototype.slice.call(mutation.target.getElementsByTagName('img')).filter(ytel);
  100. if(thumbs.length>0){
  101. thumb();
  102. }
  103. if(b==1){
  104. links=Array.prototype.slice.call(mutation.target.getElementsByTagName('a')).filter(ythref);
  105. if(links.length>0){
  106. link();
  107. }
  108. }
  109. }else{
  110. skip=Array.prototype.slice.call(mutation.target.getElementsByClassName('skipinv'));
  111. if(skip<1){
  112. title=Array.prototype.slice.call(mutation.target.getElementsByTagName('h1'));
  113. addbtn();
  114. }
  115. }
  116. });
  117. });
  118. observer.observe(document.body,{childList:true,subtree:true});